IOS现成的API里的json解析速度非常快,这里就不说了,今天对比一下Android里面json的解析库。
首先第一个是Android API里面自带的json解析,其次是谷歌提供的Gson解析库(开源),其次是在网上看到的解析很快速的阿里巴巴分享的Fastjson包。Android自带的json解析大家一定都很熟悉了,这里不介绍了,这里详细说说谷歌提供的另一套解析库Gson:
gson的使用方法非常的简单。只需要将需要解析的json字符串和对应的Bean类xing型传递给GSON类的from方法既可:Gson gson = new Gson();
List so = gson.fromJson(mJsonString, new
TypeToken>() {}.getType());
这里的beanlei类中的字段的命名要和json中的字段相同,其次实现get和set方法(稍后讲原因)。
标准的bean:import java.util.List;
public class Geo {
private String type;
private List coordinates;
public Geo() {}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List getCoordinates() {
return coordinates;
}
public void setCoordinates(List coordinates) {
this.coordinates = coordinates;
}
}
我曾经担心复杂的json结构会不会解析出现问题,但是试验了以后嵌套了其他的bean类,照样迭代赋值了。
阿里巴巴提供的fastjson库使用方法和gson一样,只是底层的原理不同。这里不详细介绍了。
下面看一下三个库解析相同的json字段的对比:(使用了25条非常复杂的Json数据)
大家可以看到谷歌提供的gson有非常大的速度优势。这里我们走进它的代码浏览一下。
找到了关键的类:JsonObject.java
package com.google.gson;
import com.google.gson.internal.LinkedTreeMap;
import java.util.Map.Entry;
import java.util.Set;
public final class JsonObject extends JsonElement
{
private final LinkedTreeMap members = new LinkedTreeMap();
JsonObject deepCopy()
{
JsonObject result = new JsonObject();
for (Map.Entry entry : this.members.entrySet()) {
result.add((String)entry.getKey(), ((JsonElement)entry.getValue()).deepCopy());
}
return result;
}
public void add(String property, JsonElement value)
{
if (value == null) {
value = JsonNull.INSTANCE;
}
this.members.put(property, value);
}
public JsonElement remove(String property)
{
return (JsonElement)this.members.remove(property);
}
public void addProperty(String property, String value)
{
add(property, createJsonElement(value));
}
public void addProperty(String property, Number value)
{
add(property, createJsonElement(value));
}
public void addProperty(String property, Boolean value)
{
add(property, createJsonElement(value));
}
public void addProperty(String property, Character value)
{
add(property, createJsonElement(value));
}
private JsonElement createJsonElement(Object value)
{
return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value);
}
public Set> entrySet()
{
return this.members.entrySet();
}
public boolean has(String memberName)
{
return this.members.containsKey(memberName);
}
public JsonElement get(String memberName)
{
return (JsonElement)this.members.get(memberName);
}
public JsonPrimitive getAsJsonPrimitive(String memberName)
{
return (JsonPrimitive)this.members.get(memberName);
}
public JsonArray getAsJsonArray(String memberName)
{
return (JsonArray)this.members.get(memberName);
}
public JsonObject getAsJsonObject(String memberName)
{
return (JsonObject)this.members.get(memberName);
}
public boolean equals(Object o)
{
return (o == this) || (((o instanceof JsonObject)) && (((JsonObject)o).members.equals(this.members)));
}
public int hashCode()
{
return this.members.hashCode();
}
}
可以看到其中使用了一个LinkedTreeMap来缓存字段与值。这里要比我们直接使用API中的方法寻找要快,其次在类ProtoTypeAdapter.java中我们找到了赋值方法:@SuppressWarnings("unchecked")
@Override
public GeneratedMessage deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
try {
JsonObject jsonObject = json.getAsJsonObject();
Class extends GeneratedMessage> protoClass =
(Class extends GeneratedMessage>) typeOfT;
try {
// Invoke the ProtoClass.newBuilder() method
Object protoBuilder = getCachedMethod(protoClass, "newBuilder")
.invoke(null);
Class> builderClass = protoBuilder.getClass();
Descriptor protoDescriptor = (Descriptor) getCachedMethod(
protoClass, "getDescriptor").invoke(null);
// Call setters on all of the available fields
for (FieldDescriptor fieldDescriptor : protoDescriptor.getFields()) {
String name = fieldDescriptor.getName();
if (jsonObject.has(name)) {
JsonElement jsonElement = jsonObject.get(name);
String fieldName = name + "_";
Field field = protoClass.getDeclaredField(fieldName);
Type fieldType = field.getGenericType();
Object fieldValue = context.deserialize(jsonElement, fieldType);
Method method = getCachedMethod(
builderClass, "setField", FieldDescriptor.class, Object.class);
method.invoke(protoBuilder, fieldDescriptor, fieldValue);
}
}
// Invoke the build method to return the final proto
return (GeneratedMessage) getCachedMethod(builderClass, "build")
.invoke(protoBuilder);
} catch (SecurityException e) {
throw new JsonParseException(e);
} catch (NoSuchMethodException e) {
throw new JsonParseException(e);
} catch (IllegalArgumentException e) {
throw new JsonParseException(e);
} catch (IllegalAccessException e) {
throw new JsonParseException(e);
} catch (InvocationTargetException e) {
throw new JsonParseException(e);
}
} catch (Exception e) {
throw new JsonParseException("Error while parsing proto: ", e);
}
}
这里通过反射类的set方法来给变量赋值,因此bean类中的变量要加上get和set方法。
文章出处: http://android-study.diandian.com/post/2013-07-11/40050907908