Gson是Google开发来用来序列化和反序列化json格式数据的java库,他最大的特点就是对复杂类型的支持度高,可以完美解决java泛型问题,这得益于他对泛型类型数据的特殊处理,他的缺点就是速度慢。
我们首先看下例子:
List<MerchantMessage> merchants = new ArrayList<MerchantMessage>(); MerchantMessage m1 = new MerchantMessage(); List<Photo> p1 = new ArrayList<Photo>(); p1.add(new Photo("zcm", "http://zcm.jpg")); m1.setPhotos(p1); m1.setAdcode("123"); m1.setAddress(123123); m1.setBusinessArea("hello"); merchants.add(m1); ResponseMerchantResult result = new ResponseMerchantResult(0, merchants); String json = Gson.toJson(result);
Gson.formJson(json,ResponseMerchantResult.class);
我们构建了一个ResponseMerchantResult类型的数据,然后执行Gson.toJson方法,然后就可以得到相应的json字符串,我们来看下解析过程
最终Gson会执行到这个方法:
@SuppressWarnings("unchecked") public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); boolean oldLenient = writer.isLenient(); writer.setLenient(true); boolean oldHtmlSafe = writer.isHtmlSafe(); writer.setHtmlSafe(htmlSafe); boolean oldSerializeNulls = writer.getSerializeNulls(); writer.setSerializeNulls(serializeNulls); try { ((TypeAdapter<Object>) adapter).write(writer, src); } catch (IOException e) { throw new JsonIOException(e); } finally { writer.setLenient(oldLenient); writer.setHtmlSafe(oldHtmlSafe); writer.setSerializeNulls(oldSerializeNulls); } }
我们来分析下:
getAdapter(TypeToken.get(typeOfSrc));
这个代码是获取到解析解析的适配器,根据typeOfSrc匹配现有的适配器,以后所有的操作就是这个适配器来完成。
@SuppressWarnings("unchecked") public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) { TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type); if (cached != null) { return (TypeAdapter<T>) cached; } Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get(); boolean requiresThreadLocalCleanup = false; if (threadCalls == null) { threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>(); calls.set(threadCalls); requiresThreadLocalCleanup = true; } // the key and value type parameters always agree FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type); if (ongoingCall != null) { return ongoingCall; } try { FutureTypeAdapter<T> call = new FutureTypeAdapter<T>(); threadCalls.put(type, call); for (TypeAdapterFactory factory : factories) { TypeAdapter<T> candidate = factory.create(this, type); if (candidate != null) { call.setDelegate(candidate); typeTokenCache.put(type, candidate); return candidate; } } throw new IllegalArgumentException("GSON cannot handle " + type); } finally { threadCalls.remove(type); if (requiresThreadLocalCleanup) { calls.remove(); } } }
我们看到这个方法会遍历所有的适配器工厂,然后得到一个合适的,我们对Gson扩展时最大的扩展点就是这个地方,你可以替换他本身的适配器工厂,也可以添加你需要的工厂。
我们来看下最常用的一个适配器工厂ReflectiveTypeAdapterFactory --- 反射类型适配器工厂类
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) { Class<? super T> raw = type.getRawType(); if (!Object.class.isAssignableFrom(raw)) { return null; // it's a primitive! } ObjectConstructor<T> constructor = constructorConstructor.get(type); return new Adapter<T>(constructor, getBoundFields(gson, type, raw)); }
最关键的就是这个create方法,这个方法最终会创建一个需要的适配器,这个适配器工厂会放在所有工厂的最后,当我们要解析的类不是基本类或常用的java类时,就会使用这个工厂来解析
我们看到getBoundFields()方法
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; } field.setAccessible(true); 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 name BoundField 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; }
看到这里我们就会发现会获取所有的字段,然后为每个字段绑定他对应的适配器,这样被解析类的每个属性都有了相应的解析适配器,接下来就可以进行解析了
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); boolean oldLenient = writer.isLenient(); writer.setLenient(true); boolean oldHtmlSafe = writer.isHtmlSafe(); writer.setHtmlSafe(htmlSafe); boolean oldSerializeNulls = writer.getSerializeNulls(); writer.setSerializeNulls(serializeNulls); try { ((TypeAdapter<Object>) adapter).write(writer, src); } catch (IOException e) { throw new JsonIOException(e); } finally { writer.setLenient(oldLenient); writer.setHtmlSafe(oldHtmlSafe); writer.setSerializeNulls(oldSerializeNulls); } }
我们看到这里会调用适配器的write方法:
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(); } }
这里会循环所有的属性,然后调用对应的适配器的write方法,最终序列化就完成了。
我觉得Gson最好的地方就是他可以自动适配泛型类型,我们来看个类
public class TypeToken<T> { final Class<? super T> rawType; final Type type; final int hashCode; @SuppressWarnings("unchecked") TypeToken(Type type) { this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type)); this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type); this.hashCode = this.type.hashCode(); } }
这个类是Gson用来记录解析过程需要的type类型,当寻找适配器时就是根据这个类来寻找符合的适配器的,所以泛型的配置也是在这个类里配置。
我们来看下怎么配置这个类
首先看几个基本类
public class GenericResult<T>{ private long l1; private double d1; private int i1; private String s1; private List<T> datas; }
public class Message<T> { private List<T> data; public List<T> getData() { return data; } public void setData(List<T> data) { this.data = data; } }
GenericResult<Message> result2 = new GenericResult<Message>(); Message<MerchantMessage> message = new Message(); message.setData(merchants); result2.setD1(11d); result2.setI1(1); result2.setL1(11l); result2.setS1("11"); result2.setDatas(Arrays.asList(message)); String json2 = JsonTool.toJson(result2);
我们看到最后这段代码,这段代码主要是构建一个java类,其中主要类是GenericResult,然后他包含泛型类型Message,Message包含泛型类型MerchantMessage
那我们解析的时候怎么解析呢
我们需要一个辅助类
下面或者类就可以记录我们所有的类型,我们看下怎么使用
public class TypeMessage implements ParameterizedType{ private final Class main; private final Type[] args; public TypeMessage(Class main,Type[] args){ this.main = main; this.args = args == null ? new Type[0] : args; } @Override public Type[] getActualTypeArguments() { return this.args; } @Override public Type getRawType() { return this.main; } @Override public Type getOwnerType() { return null; } }
JsonTool.<GenericResult>toJson(json2, new TypeMessage( GenericResult.class, new Type[]{new TypeMessage(Message.class,new Type[]{MerchantMessage.class})}))
当Gson去解析的时候就会按照我们配置的类型去解析。这样我们的泛型就被我们放置进去了。
以上就是toJson的解析,formJson的解析和toJson类似这里就不再看了。