JSON:杰克逊流解析器 - 真的值得吗?

15

我正在编写一款应用程序,其中很大程度上使用了JSON解析。 我所做的大部分工作已经使用Android内置的JSONObject库实现(难道它是json-lib吗?)。

JSONObject似乎会创建JSON字符串中的所有实例...即使我最终不使用其中的所有实例。

我的应用程序目前在G1上运行得很好。

我的问题是:使用流解析器(如Jackson)是否值得所有麻烦而带来的速度和内存优势?

所谓的麻烦是指:就我所知,与使用内置库相比,使用Jackson存在三个缺点:

  1. 依赖外部库。这会使您的.apk最终变得更大。这不是一个很大的问题。
  2. 应用程序更脆弱。由于解析不是自动完成的,因此更容易受到正在解析的JSON文本更改的影响(也许我对此是错误的)。
  3. 使用流解析器编写解析JSON的代码既丑陋又繁琐。

1
我不同意第二点。如果JSON结构以意外的方式发生变化,那么你真的会很倒霉。 - Matthew Flaschen
在某些情况下不是真的,例如将一个对象作为另一个对象的值添加。除非您在pull解析器中计划它,否则它会出错,而使用JSONObject,则可以正常工作。例如:更改{ "first_name": "Adam", "last_name": "Olsen" } 到{ "first_name": "Adam, "last_name: "Olsen", "phone_numbers": { "home": "555-867-5309", "work": "888-555-5555" } }会使您的pull解析器陷入循环,如:while(parser.nextToken() != JsonToken.END_OBJECT)
  • 您最终会提前到达END_OBJECT,而JSONObject会正确解析它。
- synic
可以编写一个流解析器来处理这个问题。我相信这就是shipChildren (http://jackson.codehaus.org/1.5.0/javadoc/org/codehaus/jackson/JsonParser.html#skipChildren%28%29)的作用所在。 - Matthew Flaschen
除非您遇到性能问题,否则API在底层执行什么操作并不重要。 - Guvante
3个回答

6
我在大多数情况下也使用内置的JSON解析器,但最近遇到一种情况它不适用:对于某些Web服务请求,我收到超过1 MB的JSON文档。使用内置的JSON解析器加载这些文档需要大量的主存储器,并导致多次OutOfMemoryException。对于这些情况,流解析器是更好的选择(尽管使用起来更加不便),而内置的JSON解析器不提供流式解析,只提供类似DOM的样式。
对于任何寻找Android流式JSON解析器的人,我强烈推荐使用Google's GSON。我首先尝试了Jackson JSON,它运行良好,直到我尝试构建应用程序的发布版本:ProGuard报告了几个问题,并且正在运行的应用程序在Jackson的ObjectMapper构造函数中崩溃,出现神秘的NullPointerException(虽然在调试版本中一切正常)。即使尝试了几个小时,我也无法修复它。然后我转而使用GSON,一切都像魅力一样工作。
顺便说一下:GSON仅支持流的jar文件大小仅为14kB,所以真的没有什么好担心的。

1
原来有一种方法可以使ProGuard保持内容不变,我的同事找到了这个方法。我希望能说服他详细介绍这个方法,并在博客上发表文章,因为它不是一行代码就能解决的问题。从根本上讲,ProGuard的弱点在于它依赖于静态分析,在反射方面容易出现问题。需要注意的是,如果只使用Jackson核心库中的流处理(JsonParser、JsonGenerator),那么应该不会出现问题。只有映射部分才会大量使用反射技术。 - StaxMan
如果我们必须使用映射器,您介意指出那些遇到NullPointerException问题的人通往解决方案的一般方向吗? - kwogger
正如我在帖子中提到的,我还没有找到“NullPointerException”的解决方案。这就是为什么我已经转向了GSON。 - sven
StaxMan提到他的同事已经解决了这个问题,尽管看起来并不是一个简单的解决方案。 - kwogger
抱歉,没有正确阅读评论... - sven
显示剩余3条评论

2

看起来你已经自己回答了这个问题。 :)
我自己使用内置的JSON解析器,从未寻找过替代方案。

编辑:现在我正在使用来自DroidParts的薄注释包装器。


2
我认为问题在于内置的是否足够好。如果是,减少依赖通常是一个好策略。足够好既可以指效率,也可以指易用性。
值得一提的是,Jackson也有一个不错的树模型以及完整的数据绑定。 树模型比默认解析器快得多(在J2SE上解析速度快3倍至5倍,在其他平台上可能也是如此,树模型本身也可能更有效率)。 或者:如果您不想依赖第二个jar包(树模型和数据绑定需要mapper),编写自己的树以满足您的用例也很简单。可以使用基本的HashMap / ArrayList / wrappers,也可以使用自己的类。构建器可能最多只需要40行代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接