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头有冲突。

时间: 2024-12-18 18:42:31

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

JSON lib 里JsonConfig详解

一,setCycleDetectionStrategy 防止自包含 /** * 这里测试如果含有自包含的时候需要CycleDetectionStrategy */ public static void testCycleObject() { CycleObject object = new CycleObject(); object.setMemberId("yajuntest"); object.setSex("male"); JsonConfig jsonCon

js 实现动态key value(JSON字符串注意事项:key和value都要用双引号,官网指定用双引号)

1.JSON字符串注意事项:key和value都要用双引号,官网指定用双引号,如下: var mapStr='{"a":"a","b":"b"}'; var map=JSON.parse(mapStr); 如此通过拼接字符串,JSON解析获得KeyValue var str='a'; map[str];//输出a 2.也是通过拼接字符串方式获得keyvalue,使用eval方法解析成数组,注意是数组 var mapStr='[

json lib 2.4及其依赖包下载

下载文件地址:https://files.cnblogs.com/files/xiandedanteng/json-lib-2.4%26dependencies_jars.rar 它包括 commons-beanutils-1.9.3.jar commons-collections-3.2.jar commons-lang-2.3.jar commons-logging-1.2.jar ezmorph-1.0.6.jar json-lib-2.4-jdk15.jar 这些库可以满足转化Java对

使用python解析Json字符串-获取Json字符串关键字

1 import json 2 3 data = { 4 "statusCode": 0, 5 "data": { 6 "totoal": "5", 7 "height": "5.97", 8 "weight": "10.30", 9 "age": "3" 10 }, 11 "msg":

tp3 key json 分页

//json 强制转换为array $arr[$key]['checkpro'] = json_decode($val['checkpro'],JSON_FORCE_ARRAY);    $arr[$key]['messpro'] = json_decode($val['messpro'],JSON_FORCE_ARRAY); {$Think.lang.$key} $pro = D('Project');        $count = $pro->where('status != -1')->

spray json, jackson 转到type时多key和少key的比较

有组合关系的三个class定义 A { B { C {...} ... } ... } 每个class都有loadFromJson和writeAsJson方法.过去几年,三个class里的成员变量一直在添加,而数据库里有很多json string类型的老数据,为了能够正确的把它们转化为class,就需要对一些域进行判断,举个例子. 在 db 中有一个json string,是这样的 name: xins, age: 24 而几年后C添加了一个新的域,company 那么loadFromJson就

RobotFramework-RequestsLibrary中To Json关键字使用中的问题

To Json的关键字主要功能是将Python字典和Json格式进行互相转换, 参数说明:         content   被转换的对象         pretty_print 默认是false,将Content 从Json转换为字典类型,如果定义为true,将Content从字典类型转换为Json 这个关键字主要是使用Python的Json类库两个方法,dumps方法(将字典转换为Json),loads方法(将Json转换为字典). 这样问题就来了,在需要使用To_Json将字典转换为J

Android json

JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. – Json.org JSON Vs XML 1.JSON和XML的数据可读性基本相同 2.JSON和XML同样拥有丰富的解析手段 3.JSON相对于XML来讲,数据的体积小 4.JSON与JavaScript的交互更加方便

转载--Json转换

JSON的全称是"JavaScript Object Notation",意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式.XML也是一种数据交换格式,为什么没 有选择XML呢?因为XML虽然可以作为跨平台的数据交换格式,但是在JS(JavaScript的简写)中处理XML非常不方便,同时XML标记比数据 多,增加了交换产生的流量,而JSON没有附加的任何标记,在JS中可作为对象处理,所以我们更倾向于选择JSON来交换数据.这篇文章主要从以下几个方