浏览 3130 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-08-11
最后修改:2011-08-12
之前fastjson没有加入对循环支持,原因有两个: 1) 对引用处理技术不够了解; 2) 对支持循环引用的性能存在担心。 这两个问题都已经一定程度得到解决,有了技术储备,性能问题也有了解决方案。性能问题的处理在于代码实现细节,不在这里讨论,我希望和大家一起讨论一下引用表示方案。 DOJO很早就发展了自己的Reference实现方案,其开发者Kris Zyp做了很多研究,包括 http://dojotoolkit.org/reference-guide/dojox/json/ref.html,这个文档描述了DOJO支持循环引用的方案, http://tools.ietf.org/id/draft-zyp-json-schema-03.html,这是Kris Zyp在ietf的提案。 http://json-schema.org/ 对引用的处理,其方案基本如下: {"$ref":"#"} // 自引用 {"$ref":"3"} // id引用 Kris Zyp做的一些研究,对我颇有启发,但是我不喜欢它表示json reference path的方案。处理引用Kris Zyp的方案最重要的是基于id的引用,这会限制范围,对实现的性能也会有影响。 w3c也关注到了json, W3C希望提供JSON+RDF的规范,http://www.w3.org/wiki/JSON+RDF,这个地址收录一些JSON技术方案。 JSON-LD也是值得参考的:http://json-ld.org/spec/latest/。JDSON-LD中有表示类型的fieldName使用@type,我觉得这个不错。 JSONPath,http://goessner.net/articles/JsonPath/。JSONPath类似XPath,我觉得这是表示引用的较好方案,我很欣赏其中的JSONPath expressions的设计,这个在java script中应该很容易实现。 现在的方案都不够成熟,都不够好,fastjson做好了,也许能够成为事实的标准。 我喜欢的表示方案: { "children":[ { "children":[{ "children":[], "id":3, "name":"系统基础", "parent":{"$ref":".."}, // 引用上一级对象 "root":{"$ref":"$"} // 引用根对象 }], "id":2, "name":"平台技术部", "parent":{"$ref":".."}, // 引用上一级对象 "root":{"$ref":".."} // 引用上一级对象 }, { "children":[], "id":4, "name":"中文站技术部", "parent":{"$ref":".."}, // 引用上一级对象 "root":{"$ref":".."} // 引用上一级对象 } ], "id":1, "name":"技术部", "root":{"$ref":"@"} // 引用自身 } 通过JSONPath来描述引用,不受对象是否存在key field限制。 DOJO风格的实现: { "children":[ { "children":[{ "children":[], "id":3, "name":"系统基础", "parent":{"$ref":"2"}, // id应用 "root":{"$ref":"1"} // id应用 }], "id":2, "name":"平台技术部", "parent":{"$ref":"3"}, // id应用 "root":{"$ref":"1"} // id应用 }, { "children":[], "id":4, "name":"中文站技术部", "parent":{"$ref":"1"}, // id应用 "root":{"$ref":"1"} // id应用 } ], "id":1, "name":"技术部", "root":{"$ref":"#"} // 引用自身 } 这种基于id的引用方式,使用范围受到限制,如果对象不存在key field,或者key field不是id,就不适用了。 这是我目前的初步方案,将会在下一次发布的fastjson中实现。 希望大家参与讨论,一起实现最好的json reference处理方案。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-08-15
貌似大家对这方案都不太关心?奇怪了
以前看过Hessian的序列化代码,也有类似Ref的实现。其实它做的比较简单, 1. 内部做了个IdentityIntMap,记录下每个object的haskKey。 2. 同时也记录一个数组,记录真实传递过程中传递的ref key列表,针对Ref的给定特定标示,hessian里为R+int(数组下标) 3. 目标端接收到传递时对应的数据后,针对每个Object对象重新构建ref key列表,最后读取传递的R+int(数组下标) 它在构造ref列表时,采取的是宁可错杀也不放过。不管什么Object都会加入到ref列表中,而且需要保证序列化和反序列化都会有相同的操作。这样通过获取ref数组下标就可以取到正确的值。 一种相对暴力,但也相对有效的一种方法 |
|
返回顶楼 | |
发表时间:2011-08-15
最后修改:2011-08-15
补充一点:
1. Ref数组都是在各自序列化和反序列化的context中存在,不会出现在传输数据上。因此只要保证两边构造Ref数组的算法一致即可 2. Ref数组并不是所有数据都会存在真实引用,所以是一种时间换空间的做法,可能白白构建了Ref数组,到头来发现根本没人引用。fastjson可以考虑做个开关,用户可以选择 |
|
返回顶楼 | |
发表时间:2011-08-15
dojo的方案我不喜欢,还是温少自己的方案比较好。把文档和注释说清楚即可。
|
|
返回顶楼 | |
发表时间:2011-08-15
agapple 写道 貌似大家对这方案都不太关心?奇怪了
以前看过Hessian的序列化代码,也有类似Ref的实现。其实它做的比较简单, 1. 内部做了个IdentityIntMap,记录下每个object的haskKey。 2. 同时也记录一个数组,记录真实传递过程中传递的ref key列表,针对Ref的给定特定标示,hessian里为R+int(数组下标) 3. 目标端接收到传递时对应的数据后,针对每个Object对象重新构建ref key列表,最后读取传递的R+int(数组下标) 它在构造ref列表时,采取的是宁可错杀也不放过。不管什么Object都会加入到ref列表中,而且需要保证序列化和反序列化都会有相同的操作。这样通过获取ref数组下标就可以取到正确的值。 一种相对暴力,但也相对有效的一种方法 谢谢agapple介绍hessian的实现方案。思路不错,值得借鉴。 不过我更倾向于使用基于path的引用表示法,而非下标表示法。 |
|
返回顶楼 | |
发表时间:2011-08-15
非常关心这个实现。事实上,一直在等这个功能出来,太需要了!!!
|
|
返回顶楼 | |
发表时间:2011-08-15
wenshao 写道 agapple 写道 貌似大家对这方案都不太关心?奇怪了
以前看过Hessian的序列化代码,也有类似Ref的实现。其实它做的比较简单, 1. 内部做了个IdentityIntMap,记录下每个object的haskKey。 2. 同时也记录一个数组,记录真实传递过程中传递的ref key列表,针对Ref的给定特定标示,hessian里为R+int(数组下标) 3. 目标端接收到传递时对应的数据后,针对每个Object对象重新构建ref key列表,最后读取传递的R+int(数组下标) 它在构造ref列表时,采取的是宁可错杀也不放过。不管什么Object都会加入到ref列表中,而且需要保证序列化和反序列化都会有相同的操作。这样通过获取ref数组下标就可以取到正确的值。 一种相对暴力,但也相对有效的一种方法 谢谢agapple介绍hessian的实现方案。思路不错,值得借鉴。 不过我更倾向于使用基于path的引用表示法,而非下标表示法。 如果是非在javascript解析带ref结构的json对象,我可能会比较建议使用hessian的那种方案。实现起来会比较简单,而且我觉得在性能上会有一定的优势,如果是path那种模式,你势必会实现一个类似于EL表达式解析属性的方式,一般人可能写的不会很好(当然你肯定能优化的不错) |
|
返回顶楼 | |
发表时间:2011-11-29
你好像我的一个高中同学。
|
|
返回顶楼 | |