Android—Gson原理解析
JsonElement
- 抽象類
- 代表json串的某一個元素
- 某一個元素:
- JsonObject
- JsonArray
- JsonPrimitive(基本類型)
- JsonNull
JsonElement的四個子類
- JsonObject、JsonArray、JsonPrimitive、JsonNull
JsonPrimitive?
該類對Java的基本類型及其對應(yīng)的對象類進(jìn)行了封裝。(短整長,單精雙精,字符<表示為單字符字符串>,布爾)
Gson對象的產(chǎn)生
通過new Gson()方式
?通過這種方式創(chuàng)建的Gson對象,將用Java的反射機制來完成json的解析,將大量默認(rèn)的TypeAdapterFactory添加到factories中,生成默認(rèn)的Gson對象
通過GsonBuilder的方式
TypeAdapter:該類的作用就是把json串封裝成你指定的Java對象
通過GsonBuilder注冊TypeAdapter,并把TypeAdapter封裝成TypeAdpterFactory對象
將封裝成的TypeAdapterFactory通過GsonBuilder的create傳入Gson對象中并返回
調(diào)用gson.fromJson方法,調(diào)用getTypeAdapter方法返回你自定義的Adapter
下面解析new?Gson()方式的序列化過程
String json = "{ \"name\":\"java書籍\", \"authors\":[\"Jerry\",\"Tom\"]}"; Book book = new Gson().fromJson(json, Book.class); String s = new Gson().toJson(book);public class Book implements Serializable {private String name;private ArrayList<String> authors;public Book(String name, ArrayList<String> authors) {this.name = name;this.authors = authors;} }反序列化過程:
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {boolean isEmpty = true;// 接受不符合規(guī)定的json變量的值boolean oldLenient = reader.isLenient();//強制設(shè)置為接受reader.setLenient(true);try { //此處相當(dāng)于調(diào)用了一次 JsonReader 中的 doPeek() 方法,返回下一個令牌的類型而不消耗它,設(shè)置當(dāng)前令牌reader.peek();isEmpty = false;//TypeToken 本質(zhì)上是 Class 的增強封裝類TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);//根據(jù)要轉(zhuǎn)化的實體類型,獲取相應(yīng)的適配器TypeAdapter<T> typeAdapter = getAdapter(typeToken);//通過適配器生成實體類T object = typeAdapter.read(reader);return object;} catch (EOFException e) {.......}}可以看到最終結(jié)果是adapter的read方法返回了我們需要的對象。
先看 getAdapter (typeToken) 方法:
因為我們采用的是new?Gson(),由于我們沒有添加自定義的Adapter,最后只能由ReflectiveTypeAdapterFactory進(jìn)行處理。
直接看ReflectiveTypeAdapterFactory的create方法:
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {Class<? super T> raw = type.getRawType();//這里用于比對類型,如果不是相應(yīng)的類型就返回null//確定此* {@code Class}對象表示的類或接口是否與指定的{{code code}}參數(shù)所表示的類或接口相同,或者是該類或接口的超類或父接口。 。如果是,則返回{@code true}; *否則返回{@code false}//很顯然,這里返回的是true 應(yīng)為我們的類是TestMode 是一個class類if (!Object.class.isAssignableFrom(raw)) {return null; // it's a primitive!}//通用對象構(gòu)造工廠ObjectConstructor<T> constructor = constructorConstructor.get(type);return new Adapter<T>(constructor, getBoundFields(gson, type, raw));}getBoundFields(gson, type, raw)方法,通過反射獲取類的屬性。
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();if (raw.isInterface()) {return result;}Type declaredType = type.getType();while (raw != Object.class) {Field[] fields = raw.getDeclaredFields();for (Field field : fields) {boolean serialize = excludeField(field, true);boolean deserialize = excludeField(field, false);if (!serialize && !deserialize) {continue;}accessor.makeAccessible(field);Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());List<String> fieldNames = getFieldNames(field);BoundField previous = null;for (int i = 0, size = fieldNames.size(); i < size; ++i) {String name = fieldNames.get(i);if (i != 0) serialize = false; // only serialize the default nameBoundField boundField = createBoundField(context, field, name,TypeToken.get(fieldType), serialize, deserialize);BoundField replaced = result.put(name, boundField);if (previous == null) previous = replaced;}if (previous != null) {throw new IllegalArgumentException(declaredType+ " declares multiple JSON fields named " + previous.name);}}type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));raw = type.getRawType();}return result; }debug截圖:
?可以看到getBoundFields()方法結(jié)果返回的result是應(yīng)該map對象,里面存著key為我們類屬性名,value為adapterFactory的對象。
了解了getAapter方法,我們接下來分析ReflectiveTypeAdapterFactory的read方法。
@Override public T read(JsonReader in) throws IOException {if (in.peek() == JsonToken.NULL) {in.nextNull();return null;}T instance = constructor.construct();try {in.beginObject();while (in.hasNext()) {String name = in.nextName();BoundField field = boundFields.get(name);if (field == null || !field.deserialized) {in.skipValue();} else {field.read(in, instance);}}} catch (IllegalStateException e) {throw new JsonSyntaxException(e);} catch (IllegalAccessException e) {throw new AssertionError(e);}in.endObject();return instance; }?
這里的field就是剛剛getBoundFields()中獲取到的,放在map中的一個。
可以看到它調(diào)用的是field.read(in, instance);
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException {Object fieldValue = field.get(value);TypeAdapter t = jsonAdapterPresent ? mapped : new TypeAdapterRuntimeTypeWrapper(context, mapped, fieldType.getType());((TypeAdapter)t).write(writer, fieldValue);}void read(JsonReader reader, Object value) throws IOException, IllegalAccessException {Object fieldValue = mapped.read(reader);if (fieldValue != null || !isPrimitive) {field.set(value, fieldValue);}}? ?根據(jù)debug截圖可以看出,fieldValue是typeAdapter調(diào)用read之后解析出來的值,就跟我們現(xiàn)在所跟的流程一樣,因為這里“java書籍“是String所以會到String對應(yīng)的Adapter中解析,如果是我們自定義類的話還是會走再一遍反射。可以看到value是Book對象,
?都還是null,field對應(yīng)的是name屬性,所以接下來set方法將fieldValue設(shè)置到Book對象的name屬性中。
?可以看到set方法后,book對象的name就有值了。
看下read方法最后返回的就是解析完成的對象,
序列化toJson同樣需要經(jīng)過反射,
可以看ReflectiveTypeAdapterFactory的write方法,
@Override public void write(JsonWriter out, T value) throws IOException {if (value == null) {out.nullValue();return;}out.beginObject();try {for (BoundField boundField : boundFields.values()) {if (boundField.writeField(value)) {out.name(boundField.name);boundField.write(out, value);}}} catch (IllegalAccessException e) {throw new AssertionError(e);}out.endObject(); }?它也是調(diào)boundField的方法,boundField.write(out, value);
@Override void write(JsonWriter writer, Object value)throws IOException, IllegalAccessException {Object fieldValue = field.get(value);TypeAdapter t = jsonAdapterPresent ? typeAdapter: new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());t.write(writer, fieldValue); }?可以看到write之后,out屬性被寫上了“name“:”java書籍“。
?最終結(jié)果返回的是writer.toString()。
?
總結(jié)
以上是生活随笔為你收集整理的Android—Gson原理解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 保守官僚 诺基亚就这样迷失在智能机时代?
- 下一篇: Dropbox推独立应用,公司估值已达1