对于超大型的Json文本,如果直接使用Gson的fromJson(String json, Class<T> classOfT)
方法将可能导致内存问题,特别是当该Json文本中存在大型数组时,因为数组是通过复制(copy)的方法扩容的,这样就很容易导致内存不足而报异常。要解决这个问题,可以使用流(stream)来处理。
具体在使用Google的Gson库时,即选择使用JsonReader来处理。它的具体做法是一个一个读取Json文本中的元素,然后写入对象。
下面是一个使用示例,先创建User和Address两个POJO。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class Address {
private String province;
private String city;
private String district;
private String StreetAddr;
private String phone;
//get和set方法省略
}
1 | public class User { |
具体如何使用JsonReader,可以参考如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98public class BigJsonTest {
private static Gson gson = new GsonBuilder().setPrettyPrinting().create();
public static void main(String[] args) throws IOException {
User user = new User();
user.setId(302919489L);
user.setName("Paul");
user.setCreateTime(new Date());
user.setAvator("https://guangzhou.myqcloud.com/avator.jpg");
List<Address> addresses = new ArrayList<>();
Address address1 = new Address("广东省", "深圳市", "南山区");
address1.setStreetAddr("留仙大道5588号");
address1.setPhone("15011112222");
addresses.add(address1);
Address address2 = new Address("北京市", "北京市", "海淀区");
address2.setStreetAddr("中关村路");
address2.setPhone("13800008888");
addresses.add(address2);
user.setReceiveAddrs(addresses);
String jsonText = new Gson().toJson(user);
User userFromJson = parse(jsonText);
System.out.println(gson.toJson(userFromJson));
}
private static User parse(String jsonText) throws IOException {
StringReader stringReader = new StringReader(jsonText);
JsonReader jsonReader = new JsonReader(stringReader);
User workerHistory = new User();
jsonReader.beginObject();
try {
while (jsonReader.hasNext()) {
String key = jsonReader.nextName();
if ("id".equals(key)) {
workerHistory.setId(jsonReader.nextLong());
} else if ("name".equals(key)) {
workerHistory.setName(jsonReader.nextString());
} else if ("receiveAddrs".equals(key)) {
List<Address> addresses = readAddressList(jsonReader);
workerHistory.setReceiveAddrs(addresses);
} else {
jsonReader.skipValue();
}
}
jsonReader.endObject();
return workerHistory;
} catch (Exception e) {
e.printStackTrace();
} finally {
stringReader.close();
try {
jsonReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private static List<Address> readAddressList(JsonReader jsonReader) throws IOException {
List<Address> registCouriers = new ArrayList<>(8);
jsonReader.beginArray();
while (jsonReader.hasNext()) {
Address courier = new Address();
registCouriers.add(courier);
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String key = jsonReader.nextName();
switch (key) {
case "province":
courier.setProvince(jsonReader.nextString());
break;
case "city":
courier.setCity(jsonReader.nextString());
break;
case "district":
courier.setDistrict(jsonReader.nextString());
break;
default:
jsonReader.skipValue();
break;
}
}
jsonReader.endObject();
}
jsonReader.endArray();
return registCouriers;
}
}
注意:jsonReader的skipValue()
在上面的使用是必要的,因为如果没有skipValue()
方法,上面循环中jsonReader.hasNext()
方法会读取到Json键值对中的value来当做key,那样就肯定不对了。
https://developer.android.com/reference/android/util/JsonReader