原文地址:http://www.donnfelker.com/hi-performance-json-parsing-in-android
温馨提示:英文水平有限,仅供参考,欢迎拍砖!
在android开发中,我们有时候需要访问一个第三方的API,来请求一大块JSON格式的数据。现在,我其中的一个客户端,有一个用来向设备同步数据的API接口。一旦调用该API接口将会返回一个包含成千上万条JSON数据格式的结果。如果以JSON文件格式保存下来,则该文件大小达到8MB以上。将其完全的加载到内存中去是很痛苦的,并且在很多内存受限的设备上会造成奔溃。然而,使用Jackson这个JSON解析库,你能够使用流的方式将http-request作为一个输入流(reader)封装到Jacksons Streaming API中。该API能够让你在通信管道中有数据的时候,尽可能快的处理每一个json object对象。这使得你能够在通信管道中分段处理数据而非先把整个JSON文件加载进来。
我在Jackson中使用ObjectMapper将JSON数据转换为一个POJO类。这使得我的APP通过domain objects能够很好的工作,因此我无需担心所有地方的JSON解析操作(或者使用游标将数据移动到本地的数据库当中)。如果你需要将整个JSON文件与对象映射起来,你需要创建一个巨大无比的对象,这样很容易到达内存的边界,直到让你得到一个OutOfMemory的异常。正确的做法是,当数据来了我逐条解析JSON数据,但这也得益于使用POJO。下面是具体例子。
The ObjectModel
下面我们有一个简单的customer对象需要下载下来。想象一下,一个大型的会计类APP有着上百万的顾客。每一个顾客将会被转换为如下的POJO类。
public class Customer {
String firstName;
String lastName;
// 20 Other properties
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
// all the other mutators and accessors
}
Connection to the API/Consuming the stream
这实际上相当简单。选择你的网络框架(我使用的是http-request),简单的访问你的API接口。使用HttpRequest的reader()
方法,然后通过这个输入流转换为JsonPraser(如下),然后循环创建每一个Customer,最后我就有了每一个customer的实例。可参考注释。
// Connect to your API with your http lib, i use http-request: https://github.com/kevinsawicki/http-request
// Then get the reader. The 'request' variable below is just a HttpRequest object
// as shown here: http://kevinsawicki.github.io/http-request/
final Reader reader = request.reader();
final ObjectMapper mapper = new ObjectMapper();
final JsonFactory factory = mapper.getFactory();
// Create a new streaming parser with the reader
JsonParser jp = factory.createParser(reader);
// I'm working with a JSON Array that is returned from the API that I'm connecting to, so I need to advance the
// parser to the start of the array.
// Advance stream to START_ARRAY first:
jp.nextToken();
// Parse each value by looking for each start object. The Mapper will read the object and advance the parser
// until it finds the END_OBJECT at which time the mapper then deserializes into a POJO. Then the loop will
// continue to the next position. This will handle each JSON object as it becomes available and will be very
// light on memory and high in performance.
while(jp.nextToken() == JsonToken.START_OBJECT) {
// Get customer POJO
final Customer c = mapper.readValue(jp, Customer.class);
// Update local db with customer info.
myDataLayer.updateCustomer(c);
}
如何使用Jackson
简单的将它作为一个库引用,或者如果你使用的是Maven,往pom文件中添加依赖。现在,你可以处理巨大的json流,而不用再担心你的内存溢出了。
想及时了解最新信息。扫一扫,添加关注微信公众号
weixin.jpg
网友评论