当前位置: 代码迷 >> JavaScript >> fastjson兑现自省功能优化
  详细解决方案

fastjson兑现自省功能优化

热度:788   发布时间:2012-06-27 14:20:09.0
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 
1 楼 wuku 2011-09-26  
温少,你太给力了!!!做开源做到你这个份上,真是太佩服了。如果淘宝里都是像你这么有责任心的人,淘宝想不发都难
2 楼 littleJava 2011-09-30  
fastjson 不支持 List<Class> 类型的数据吗?

根据官网的示例:
http://119.38.217.15/wiki/display/FastJSON/JavaBean+to+JSONString
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 : null
	at 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用来占位,
如果缺少了,就会错误,

仅仅猜测而已。

路过。
  相关解决方案