[HTTP那些事]超大JSON文本
Posted stay4it
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HTTP那些事]超大JSON文本相关的知识,希望对你有一定的参考价值。
扩展阅读:
[HTTP那些事] JSON数据
[HTTP那些事]JSON反序列化
在JSON反序列化一文的最后,有提到,如果有1M的JSON文本应该如何来解析?
1M的JSON String,不管用GSON,fastjson,jackson,估计都要OOM了吧。本来我想说200M的JSON数据的,想想这太坑了,就改说1M了。
答案,用JsonReader读流。比如说:
public User readUser(JsonReader reader) throws IOException
String username = null;
int followersCount = -1;
reader.beginObject();
while (reader.hasNext())
String name = reader.nextName();
if (name.equals("name"))
username = reader.nextString();
else if (name.equals("followers_count"))
followersCount = reader.nextInt();
else
reader.skipValue();
reader.endObject();
return new User(username, followersCount);
我去,要手写JSON解析了,这太麻烦了吧。。。
但是你想,跟性能比起来,这些体力也不算什么了吧。
上述没太多特别的地方,你可以直接看JsonReader的源码注释,里面有详细的用法示例。
在这里呢,我们先说说如何让JsonReader来读大JSON文本。
FileReader in = new FileReader(path);
JsonReader reader = new JsonReader(in);
首先,你得先把JSON文本以文件的形式存到SD卡上。再通过FileReader拿到文件流,再通过JsonReader来读流,读流的方式也就意味着是顺序读的,所以即使它不是正确的json格式,也会一直读到错误为止。
JsonReader对手写的json解析语法非常严格,写错是非常头疼的事,另外建议把nodeName变为常量去做判断,不然以后改变量名得哭瞎。
当然,Stay肯定不会讲这么简单的东西,我们怎么跟HTTP框架结合在一起呢?这解析过程肯定也是耗时操作,我总不能先用框架把数据当文件下载下来,然后再开一个线程来解析吧。这才是最蛋疼的地方。
可惜原生Volley都不支持文件下载,这里我就拿自己的HTTP框架做演示了。
简单说下实现过程:
- 首先写个接口,比如JsonReaderable,里面定义一个方法readFromJson(JsonReader reader)
- 让你想要被反序列化的对象pojo实现这个接口,比如这样
- 让框架先把数据当文件下载到SD卡
- 在callback之前再bindData,比如这样 这样就能将json数据自动反序列化成对象callback回去了。你只需要在每个对象pojo中实现readFromJson方法就好了。
- 如果是jsonarray怎么办,我们要返回一个ArrayList啊。比如这样
- 一个好的框架相当的重要啊,我们再来看外层的调用 应该不用解释吧,都能看懂。
这种情况虽然比较少见,但在一些erp啊,sap项目中经常会遇到(别问Stay怎么知道)如果你也见过android上500M的数据库,那这些心得你都能自己领悟到了。
现在我们在App中基本采取的都是分页,一般来说不需要用JsonReader,但如果Json数据超过10K以上,pojo的复杂度特别高,并且还有嵌套时,你应该考虑使用。
你也许会问,500M,即使用JsonReader读流生成对象了,内存也装不下呀。没事,你可以通过ormapping型数据库框架来存数据,比如说读200个对象存一次,清一次。或者你可以用接口回调的方式扔给外层处理,onPartialDataBinding(ArrayList list)
其实这个扩展其他第三方框架也没什么问题,只要思路有了,实现起来也就很容易了。
框架最好是根据App具体的需求以及使用场景来定制,仅会调用哪些开源lib,看不懂,改不了,这样只能让自己在技术路上越走越窄。
就写到这里,别问Stay要代码哈,只讲思维与解决方案,如果你想知道这个HTTP框架是如何从0到1的写出来的,可以看看Stay出的课程自己动手写http框架
以上是关于[HTTP那些事]超大JSON文本的主要内容,如果未能解决你的问题,请参考以下文章