Json解析速度比較-Android API、Gson、Fastjson

     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數據)

1B955A8EDA97DCDEA82EA01F4E785640_B500_90

 

大家可以看到谷歌提供的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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章