IOS现成的API里的json解析速度非常快,这里就不说了,今天对比一下Android里面json的解析库。

首先第一个是Android API里面自带的json解析,其次是谷歌提供的Gson解析库(开源),其次是在网上看到的解析很快速的阿里巴巴分享的Fastjson包。Android自带的json解析大家一定都很熟悉了,这里不介绍了,这里详细说说谷歌提供的另一套解析库Gson:

    gson的使用方法非常的简单。只需要将需要解析的json字符串和对应的Bean类xing型传递给GSON类的from方法既可:

Gson gson = new Gson();
List<StatusObject> so = gson.fromJson(mJsonString, new  
                            TypeToken<List<StatusObject>>() {}.getType());

这里的beanlei类中的字段的命名要和json中的字段相同,其次实现get和set方法(稍后讲原因)。

标准的bean:

import java.util.List;
                                                     
public class Geo {
                                                     
    private String type;
                                                         
    private List<Float> coordinates;
                                                         
    public Geo() {}
                                                     
    public String getType() {
        return type;
    }
                                                     
    public void setType(String type) {
        this.type = type;
    }
                                                     
    public List<Float> getCoordinates() {
        return coordinates;
    }
                                                     
    public void setCoordinates(List<Float> coordinates) {
        this.coordinates = coordinates;
    }
                                                         
}

我曾经担心复杂的json结构会不会解析出现问题,但是试验了以后嵌套了其他的bean类,照样迭代赋值了。

阿里巴巴提供的fastjson库使用方法和gson一样,只是底层的原理不同。这里不详细介绍了。

 

下面看一下三个库解析相同的json字段的对比:(使用了25条非常复杂的Json数据)

Json解析速度比较-Android API、Gson、Fastjson_Json解析、Android API、G

 

大家可以看到谷歌提供的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<String, JsonElement> 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<Map.Entry<String, JsonElement>> 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