在 Android 3.0 API 11 的更新中,android.util 包下增加了 JSONReader 和 JSONWriter 等新的 json 解析类库,官方文档上已经将用法讲的差不多了,本文算是对官方文档的一个精简整理。
JSONReader
JSONReader 从名字就可以知道是来读取 json 字符串的,下面来看看具体怎么解析 JSON
解析 JSON
-
处理 JSON 对象
先调用 beginObject(),然后循环读取数据,直到 hasNext() 返回 false,最后调用 endObject()。
-
处理 JSON 数组
先调用 beginArray(),然后循环读取数据,直到 hasNext() 返回 false,最后调用 endArray()。
当碰到一个嵌套的对象或数组时,调用相应的处理方法。碰到不知道的 key 的键值对时,可以使用 skipValue() 跳过,
总结下来就是
JsonReader reader = new JsonReader(...);
reader.beginXXX();
while(reader.hasNext){
...
}
reader.endXXX();
栗子
目标 JSON
[
{
"id": 912345678901,
"text": "How do I read JSON on Android?",
"geo": null,
"user": {
"name": "android_newb",
"followers_count": 41
}
},
{
"id": 912345678902,
"text": "@android_newb just use android.util.JsonReader!",
"geo": [50.454722, -104.606667],
"user": {
"name": "jesse",
"followers_count": 2
}
}
]
public List readJsonStream(InputStream in) throws IOException {
JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
try {
return readMessagesArray(reader);
finally {
reader.close();
}
}
public List readMessagesArray(JsonReader reader) throws IOException {
List messages = new ArrayList();
reader.beginArray();
while (reader.hasNext()) {
messages.add(readMessage(reader));
}
reader.endArray();
return messages;
}
public Message readMessage(JsonReader reader) throws IOException {
long id = -1;
String text = null;
User user = null;
List geo = null;
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("id")) {
id = reader.nextLong();
} else if (name.equals("text")) {
text = reader.nextString();
} else if (name.equals("geo") && reader.peek() != JsonToken.NULL) {
geo = readDoublesArray(reader);
} else if (name.equals("user")) {
user = readUser(reader);
} else {
reader.skipValue();
}
}
reader.endObject();
return new Message(id, text, user, geo);
}
public List readDoublesArray(JsonReader reader) throws IOException {
List doubles = new ArrayList();
reader.beginArray();
while (reader.hasNext()) {
doubles.add(reader.nextDouble());
}
reader.endArray();
return doubles;
}
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);
}}
JSONWriter
说明
- 要写入数组时,首先调用 beginArray()。 之后为每个数组元素调用value(boolean)方法写入适当的值或嵌套其他数组和对象。 最后使用 endArray() 来关闭数组的输出。
- 要写入对象时,首先调用 beginObject()。 之后为写入对象的每个属性,使用属性名交替调用 name(String) 方法。 使用 value(boolean) 方法写入适当之值或嵌套其他数组和对象。 最后使用 endObject() 来关闭对象的输出。
栗子
还是之前的 json,这次是要将对象写成 json
public void writeJsonStream(OutputStream out, List messages) throws IOException {
JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8"));
writer.setIndent(" ");
writeMessagesArray(writer, messages);
writer.close();
}
public void writeMessagesArray(JsonWriter writer, List messages) throws IOException {
writer.beginArray();
for (Message message : messages) {
writeMessage(writer, message);
}
writer.endArray();
}
public void writeMessage(JsonWriter writer, Message message) throws IOException {
writer.beginObject();
writer.name("id").value(message.getId());
writer.name("text").value(message.getText());
if (message.getGeo() != null) {
writer.name("geo");
writeDoublesArray(writer, message.getGeo());
} else {
writer.name("geo").nullValue();
}
writer.name("user");
writeUser(writer, message.getUser());
writer.endObject();
}
public void writeUser(JsonWriter writer, User user) throws IOException {
writer.beginObject();
writer.name("name").value(user.getName());
writer.name("followers_count").value(user.getFollowersCount());
writer.endObject();
}
public void writeDoublesArray(JsonWriter writer, List doubles) throws IOException {
writer.beginArray();
for (Double value : doubles) {
writer.value(value);
}
writer.endArray();
}}
这就是 JSONReader 和 JSONWriter 了,算是以流的方式来读写 JSON,对于结构复杂的 JSON 来说,不拆分方法的话,各种 while 嵌套一定会让人崩溃的…