读书人

fastjson兑现自省功能优化

发布时间: 2012-06-27 14:20:09 作者: rapoo

fastjson实现自省功能优化
JSON标准是不支持自省的,也就是说如下的JSON文本,你不知道它是什么类型:

{"id":12,"name":"魏嘉留"}


fastjson支持传入类型信息,例如:

String text = ...; // {"id":12,"name":"魏嘉留"}JSON.parseObject(text, Employee.class);


如果序列化时,使用WriteClassName的特性,JSON文本是这样:
Employee x = ...;String text = JSON.toJSONString(x, SerializerFeature.WriteClassName);

上面例子中的JSON文本是:
{“@type”:"com.alibaba.demo.Employee", "id":12,"name":"魏嘉留"}


带有@type属性的文本将会被自动识别类型,上面的文本可以这样处理:
Employee x = (Employee) JSON.parse(text);


这就是Fastjson支持的自省功能。

但是使用WriteClassName之后,json文本的大小增加了许多,这个怎么办呢?fastjson 1.1.6版本将会做优化处理,非必要,不输出类型信息。
class A {B getB();setB(B b);}


类A拥有属性B,A和B都是对象,但是反序列化的时候,能够根据Property的类型信息得到B的类型,这时只需要输出A的类型,不需要输出B的类型信息。

例如:
{"@type":"com.alibaba.json.demo.A","b":{"id":0}}


在1.1.5之前的版本则会如下:
{"@type":"com.alibaba.json.demo.A","b":{"@type":"com.alibaba.json.demo.B","id":0}}


通过这种办法可以用List<T>类型的属性,由此能够减少冗余不必要的类型信息。

如下是一些测试用例:
http://code.alibabatech.com/svn/fastjson/trunk/fastjson/src/test/java/com/alibaba/json/test/bvt/writeClassName/WriteClassNameTest2.java

http://code.alibabatech.com/svn/fastjson/trunk/fastjson/src/test/java/com/alibaba/json/test/bvt/writeClassName/WriteClassNameTest_List2.java 
public class Group { private Long id; private String name; private List<User> users = new ArrayList<User>(); private List<Class> clzes = new ArrayList<Class>(); /** setter && getter **/}

新增属性 clzes
序列化成功,反序列化失败
    public void serialize() {        Group group = new Group();        group.setId(0L);        group.setName("admin");        User guestUser = new User();        guestUser.setId(2L);        guestUser.setName("guest");        User rootUser = new User();        rootUser.setId(3L);        rootUser.setName("root");        group.getUsers().add(guestUser);        group.getUsers().add(rootUser);        group.getClzes().add(Integer.class);        group.getClzes().add(int.class);        String jsonString = JSON.toJSONString(group);        System.out.println(jsonString);        Group group2 = JSON.parseObject(jsonString, Group.class); }

代码在生产 group2 提示
com.alibaba.fastjson.JSONException: not support type : nullat com.alibaba.fastjson.parser.deserializer.DefaultObjectDeserializer.deserialze(DefaultObjectDeserializer.java:246)at Fastjson_ASM_Group_1.deserialze(Unknown Source)at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:377)at com.alibaba.fastjson.JSON.parseObject(JSON.java:198)at com.alibaba.fastjson.JSON.parseObject(JSON.java:158)at com.alibaba.fastjson.JSON.parseObject(JSON.java:273)at org.netease.socketio.util.FastjsonTest.serialize(FastjsonTest.java:50)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)at org.junit.runners.ParentRunner.run(ParentRunner.java:236)at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
3 楼 wenshao 2011-10-08 回复 littleJava,List<Class>反序列化的BUG已经修正。http://code.alibabatech.com/jira/browse/FASTJSON-104 4 楼 runfriends 2011-10-09 温少:
为什么下述用fastjson序列化的json串不能用firefox自带JSON解析器反序列化成js对象
fastjson序列化结果:[{"accessFlag":"1","desc":"用户定位\r\n\r\nZBP_PER_SEARCH_CONDITION \r\n个人信息搜索\r\n \r\nImport S-CONDITION NAME BIRTHDAY\r\n \r\nExport T-SEARCHRES T-RETURN","endClassname":"com.hiaward.xbankmibs.bpm.service.accountIgt.action.BPSearchEndAction","escnname":"用户定位\n\n ZBP_PER_SEARCH_CONDITION \n 个人信息搜索\n \n Import S-CONDITION NAME BIRTHDAY\n \n Export T-SEARCHRES T-RETURN","exceptionflag":0,"id":269,"isParent":true,"journalflag":0,"projectid":1,"remoteAccessType":"1","remoteAccessUrl":"","routerId":"0000000001","serviceHandlerType":"0","servicename":"ES-EX-SearchClientInfoHead-T","servicenum":"ES-EX-SearchClientInfoHead-T","startClassname":"com.hiaward.xbankmibs.bpm.service.accountIgt.action.SearchClientStartAction","type":1,"uptime":1316669923890,"version":""}]
jackson序列化结果
{
"id": 269,
"type": 1,
"domain": null,
"version": "",
"servicename": "ES-EX-SearchClientInfoHead-T",
"servicenum": "ES-EX-SearchClientInfoHead-T",
"escnname": "用户定位\n\n\t\t\tZBP_PER_SEARCH_CONDITION \n\t\t\t个人信息搜索\n\t\t\t\n\t\t\tImport S-CONDITION NAME BIRTHDAY\n\t\t\t\n\t\t\tExport T-SEARCHRES T-RETURN",

"projectid": 1,
"prodesc": null,
"developer": null,
"journalflag": 0,
"routerId": "0000000001",
"serviceCategory": null,
"desc": "用户定位\r\n\r\nZBP_PER_SEARCH_CONDITION \r\n个人信息搜索\r\n\t\t\t\r\nImport S-CONDITION NAME BIRTHDAY\r\n\t\t\t\r\nExport T-SEARCHRES T-RETURN",
"desc": "用户定位\r\n\r\nZBP_PER_SEARCH_CONDITION \r\n个人信息搜索\r\n \r\nImport S-CONDITION NAME BIRTHDAY\r\n \r\nExport T-SEARCHRES T-RETURN"
"accessFlag": "1",
"remoteAccessType": "1",
"remoteAccessUrl": "",
"serviceHandlerType": "0",
"asname": null,
"endClassname": "com.hiaward.xbankmibs.bpm.service.accountIgt.action.BPSearchEndAction",
"startClassname": "com.hiaward.xbankmibs.bpm.service.accountIgt.action.SearchClientStartAction",
"cpcflag": null,
"exceptionflag": 0,
"uptime": 1316669923890,
"usableflag": null,
"wipeoff": null,
"refedByProdesc": null,
"isParent": true,
"trTemplate": null
}
我在firefox使用 JSON.parse()解析上述json串时出错
错误内容是:SyntaxError: JSON.parse: bad control character in string literal
而我用jackson就不会出错。
两个库的惟一不同在于原java对象的属性值,连贯的\t在fastjson都被序列化成了一个空格,而jackson没有针对\t做这样的处理。
请温少指教。
为什么fastjson要针对\t做这样的处理?另外我实在找不到firefox JSON不能反序列化上述fastjson生成的json串的原因。 5 楼 aochant 2011-10-18 我想拍一砖,这两天拜读了sql parser,没注释,文档就几行测试代码,
只能看源码,源码写得很漂亮,鄙人实在不才 ,看得很吃力
这开源开得也太没诚意了,起码写写实现思路啥的吧 亲
6 楼 robinfoxnan 2011-10-30 TO runfriends :
我猜,那些\t之间可能是空值,或者什么的,
\t用来占位,
如果缺少了,就会错误,

仅仅猜测而已。

路过。

读书人网 >JavaScript

热点推荐