json-lib关键字class作为key产生的bug

   昨天用java写一个xml序列化成json的递归算法的时候遇到一个问题,遇到一个问题,就是用class做xml的元素或者属性的节点序列化不成功。后来,单步调试的时候,发现数据其实是从xml中读出来了的,并且存入了json对象中,但是在返回的时候没有返回成功。下面是xml序列化成json的方法:

 1 /**

 2      * 迭代某元素,属性,文本,及下级元素,并将其转换为json对象

 3      */

 4    public  static JSONObject xmlToJson(Element e){

 5             JSONObject json=new JSONObject();

 6             //查看是否有文本数据

 7             String text=e.getTextTrim();

 8             if (text.length()!=0) {

 9                 json.put(R.S.TEXT,text);

10             }

11             //查看元素是否有属性

12             List<Attribute> attrs=e.attributes();

13             for (Attribute attr : attrs) {

14                 json.put(attr.getName(),attr.getValue());

15             }

16             //查看元素是否包含元素

17             List<Element> es=e.elements();

18             for (Element ele : es) {

19                  List<Element> elecount=e.elements(ele.getQName());

20                //说明该元素是唯一的,不做数组处理

21                  if (elecount.size()==1) {

22                         json.put(ele.getName(),xmlToJson(ele));

23                  }

24                  //说明该元素不是唯一的,应该以数组处理

25                  if (elecount.size()>1) {

26                      //之前已经遍历过了,此次不需要再遍历

27                      if (elecount.indexOf(ele)>0) {

28                             continue;

29                         }

30                     JSONArray arr=new JSONArray();

31                     String key=null;

32                     for (Element el: elecount) {

33                         if (key==null) {

34                             key=el.getName();

35                         }

36                         arr.add(xmlToJson(el));

37                     }

38                     json.put(key,arr);

39                 }

40             }

41             return json;

42    }
java code

下面是被测试的xml代码:

 1     <!-- 实体类/entity/bean/pojo配置 -->

 2     <ll:entitys>

 3        <ll:pakage pakage="author.liulang.mybatis.entity"/>

 4        <ll:save path="author/liulang/mybatis/entity/"/>

 5        <ll:attr equal="public" getter="public" filed="private" hash="public" public="public" serial="true" setter="public" static="false" tostring="public"/>

 6        <ll:parent class="author.liulang.common.entity.BasicEntity"/>

 7        <ll:types>

 8          <ll:type db="int" java="int"/>

 9          <ll:type db="intunsigned" java="int"/>

10          <ll:type db="integer" java="int"/>

11          <ll:type db="char" java="String"/>

12          <ll:type db="tinyint" java="int"/>

13          <ll:type db="bigint" java="long"/>

14          <ll:type db="date" java="java.util.Date"/>

15          <ll:type db="datetime" java="java.util.Date"/>

16          <ll:type db="varchar" java="String"/>

17          <ll:type db="double" java="double"/>

18          <ll:type db="decimal" java="java.math.BigDecimal"/>

19          <ll:type db="float" java="float"/>

20          <ll:type db="text" java="String"/>

21          <ll:type db="int" java="int"/>

22        </ll:types>

23     </ll:entitys>
xml code

下面是调用测试代码:

1    public static void main(String[] args) {

2         XmlUtils.setPath(C.F.X.LiuLang);

3      Element root= XmlUtils.open();

4      Element entitys = root.element("entitys");

5      JSONObject json= XmlUtils.xmlToJson(entitys);

6      System.err.println(json);

7      

8   }
caller Code

下面是调用后返回json代码的结果:

 1 {

 2     "pakage": {

 3         "pakage": "author.liulang.mybatis.entity"

 4     },

 5     "save": {

 6         "path": "author/liulang/mybatis/entity/"

 7     },

 8     "attr": {

 9         "equal": "public",

10         "getter": "public",

11         "filed": "private",

12         "hash": "public",

13         "public": "public",

14         "serial": "true",

15         "setter": "public",

16         "static": "false",

17         "tostring": "public"

18     },

19     "parent": {},

20     "types": {

21         "type": [

22             {

23                 "db": "int",

24                 "java": "int"

25             },

26             {

27                 "db": "intunsigned",

28                 "java": "int"

29             },

30             {

31                 "db": "integer",

32                 "java": "int"

33             },

34             {

35                 "db": "char",

36                 "java": "String"

37             },

38             {

39                 "db": "tinyint",

40                 "java": "int"

41             },

42             {

43                 "db": "bigint",

44                 "java": "long"

45             },

46             {

47                 "db": "date",

48                 "java": "java.util.Date"

49             },

50             {

51                 "db": "datetime",

52                 "java": "java.util.Date"

53             },

54             {

55                 "db": "varchar",

56                 "java": "String"

57             },

58             {

59                 "db": "double",

60                 "java": "double"

61             },

62             {

63                 "db": "decimal",

64                 "java": "java.math.BigDecimal"

65             },

66             {

67                 "db": "float",

68                 "java": "float"

69             },

70             {

71                 "db": "text",

72                 "java": "String"

73             },

74             {

75                 "db": "int",

76                 "java": "int"

77             }

78         ]

79     }

80 }
json Code

通过结果看到,json对象的parent字段为空,而实际该字段的结果应该为{"class":"author.liulang.common.entity.BasicEntity"},不信我们把xml文件的parent元素class属性缓存cls,那么我们可以看到返回的结果中parent字段为:{"cls":"author.liulang.common.entity.BasicEntity"}:

下面是改后的xml代码:

 1 <!-- 实体类/entity/bean/pojo配置 -->

 2     <ll:entitys>

 3        <ll:pakage pakage="author.liulang.mybatis.entity"/>

 4        <ll:save path="author/liulang/mybatis/entity/"/>

 5        <ll:attr equal="public" getter="public" filed="private" hash="public" public="public" serial="true" setter="public" static="false" tostring="public"/>

 6        <ll:parent cls="author.liulang.common.entity.BasicEntity"/>

 7        <ll:types>

 8          <ll:type db="int" java="int"/>

 9          <ll:type db="intunsigned" java="int"/>

10          <ll:type db="integer" java="int"/>

11          <ll:type db="char" java="String"/>

12          <ll:type db="tinyint" java="int"/>

13          <ll:type db="bigint" java="long"/>

14          <ll:type db="date" java="java.util.Date"/>

15          <ll:type db="datetime" java="java.util.Date"/>

16          <ll:type db="varchar" java="String"/>

17          <ll:type db="double" java="double"/>

18          <ll:type db="decimal" java="java.math.BigDecimal"/>

19          <ll:type db="float" java="float"/>

20          <ll:type db="text" java="String"/>

21          <ll:type db="int" java="int"/>

22        </ll:types>

23     </ll:entitys>
xml Code

下面是改后返回的json对象:

 1 {

 2     "pakage": {

 3         "pakage": "author.liulang.mybatis.entity"

 4     },

 5     "save": {

 6         "path": "author/liulang/mybatis/entity/"

 7     },

 8     "attr": {

 9         "equal": "public",

10         "getter": "public",

11         "filed": "private",

12         "hash": "public",

13         "public": "public",

14         "serial": "true",

15         "setter": "public",

16         "static": "false",

17         "tostring": "public"

18     },

19     "parent": {

20         "cls": "author.liulang.common.entity.BasicEntity"

21     },

22     "types": {

23         "type": [

24             {

25                 "db": "int",

26                 "java": "int"

27             },

28             {

29                 "db": "intunsigned",

30                 "java": "int"

31             },

32             {

33                 "db": "integer",

34                 "java": "int"

35             },

36             {

37                 "db": "char",

38                 "java": "String"

39             },

40             {

41                 "db": "tinyint",

42                 "java": "int"

43             },

44             {

45                 "db": "bigint",

46                 "java": "long"

47             },

48             {

49                 "db": "date",

50                 "java": "java.util.Date"

51             },

52             {

53                 "db": "datetime",

54                 "java": "java.util.Date"

55             },

56             {

57                 "db": "varchar",

58                 "java": "String"

59             },

60             {

61                 "db": "double",

62                 "java": "double"

63             },

64             {

65                 "db": "decimal",

66                 "java": "java.math.BigDecimal"

67             },

68             {

69                 "db": "float",

70                 "java": "float"

71             },

72             {

73                 "db": "text",

74                 "java": "String"

75             },

76             {

77                 "db": "int",

78                 "java": "int"

79             }

80         ]

81     }

82 }
json Code

可以看到这时候json对象的parent字段不再为空,而是{"cls":"author.liulang.common.entity.BasicEntity"},那么我们可以初步得出结论,json对象不能解析key为class的数据,到底是不是这样呢?上面的代码因为涉及到递归,和一些其他相关联的步骤,并不能很好的说明这是json-lib的bug,好的下面我们来做一个进一步验证:

这里我在main方法中写了一段代码如下:

1    public static void main(String[] args) {

2        JSONObject json=new JSONObject();

3        json.put("class","我用class做了json对象的key");

4        System.err.println(json);

5        JSONObject json2=new JSONObject();

6        json2.put("class",json);

7        System.err.println(json2); 

8   }

下面做四个选项,你们猜猜答案是什么:

A.{"class":"我用class做了json对象的key"}

{"class":{"class":"我用class做了json对象的key"}}

B.{"class":}
{"class":{}}

C.{"class":"我用class做了json对象的key"}
{"class":{}}

D.{"class":}
{"class":{"class":"我用class做了json对象的key"}}

     如果按照正常情况,答案是A,可是用了关键字class作为key,答案确奇迹般的变成了C,这可以说是json-lib的一个bug了吧,我测试了其它部分关键字,尚未发现该现象。至于造成这种结果的原因还不明确,估计是因为json-lib中用过反射的缘故。

     通过这个问题也给我们提个醒:在编程中,定义字符串,变量名,属性名,元素名,方法名的时候虽然要做到见名知意,但是也应该尽量避免与系统中保留关键字,或者是重要关键字重名,遇到这种情况最好是采用该词的简写或者同义词代替,不然在编程中可能给我们带来不必要的麻烦,与此类似的问题,还比如JavaScript中,如果你定义的一个方法名恰好为accept,而且单独定义在一个js文件中,你会发现在调用该方法的时候,浏览器会报错,说这不是一个方法。accept我查过不是JavaScript关键字,其中的原因多半应该是与系统全局方法名或者属性名重复了,或者是与header头有冲突。

你可能感兴趣的:(json-lib)