1.反序列化
1.public <T> T fromJson(String json, Class<T> classOfT)
2.public <T> T fromJson(String json, Type typeOfT)
3.public <T> T fromJson(Reader json, Class<T> classOfT)
4.public <T> T fromJson(Reader json, Type typeOfT)
5.public <T> T fromJson(JsonReader reader, Type typeOfT)
6.public <T> T fromJson(JsonElement json, Class<T> classOfT)
7.public <T> T fromJson(JsonElement json, Type typeOfT)
基本使用到的及时以上几个方法,而大家通常使用的是前面两个方法。
第一中方法只能解析基本的对象类型:包装类型,以及自定义的实体类型:
Student student = gson.fromJson(s1, Student.class);
int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson(""abc"", String.class);
String anotherStr = gson.fromJson("["abc"]", String.class);
然后再来看看具体的解析过程:
1.这里把Class类型强转成Type类型,然后再调用fromJson方法:
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
2.这里将json字符串封装成StringReader,然后再调用fromJson方法:
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
3.这里将StringReader封装成JsonReader,然后再调用fromJson方法:
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = new JsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
4.最后调用的是该方法:
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
reader.peek();
isEmpty = false;
TypeAdapter<T> typeAdapter = (TypeAdapter<T>) getAdapter(TypeToken.get(typeOfT));
return typeAdapter.read(reader);
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return null for empty
* documents instead of throwing.
*/
if (isEmpty) {
return null;
}
throw new JsonSyntaxException(e);
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
throw new JsonSyntaxException(e);
} finally {
reader.setLenient(oldLenient);
}
}
该方法中通过getAdapter方法获得对应typeOfT类型的的TypeAdapter对象,那具体是怎么获得的呢?接下来看:
5.这里先从缓存的map中获取TypeAdapter对象,如果没有就遍历下面的factories工厂集合,
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
// the key and value type parameters always agree
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
try {
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);
}
}
6.接下来看下在gson的构造函数中初始化的factories集合到底添加了哪些用于创建对应对象类型的TypeAdapter对象的工厂,:
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// user's type adapters
factories.addAll(typeAdapterFactories);
// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
factories.add(TypeAdapters.INTEGER_FACTORY);
factories.add(TypeAdapters.BOOLEAN_FACTORY);
factories.add(TypeAdapters.BYTE_FACTORY);
factories.add(TypeAdapters.SHORT_FACTORY);
factories.add(TypeAdapters.newFactory(long.class, Long.class,
longAdapter(longSerializationPolicy)));
factories.add(TypeAdapters.newFactory(double.class, Double.class,
doubleAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.NUMBER_FACTORY);
factories.add(TypeAdapters.CHARACTER_FACTORY);
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
factories.add(TypeAdapters.URL_FACTORY);
factories.add(TypeAdapters.URI_FACTORY);
factories.add(TypeAdapters.UUID_FACTORY);
factories.add(TypeAdapters.LOCALE_FACTORY);
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingPolicy, excluder));
this.factories = Collections.unmodifiableList(factories);
比如基本的TypeAdapter对象的工厂都位于TypeAdapters类中,这里可以举例看看TypeAdapters.STRING_FACTORY的工厂:
public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);
public static <TT> TypeAdapterFactory newFactory(
final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
}
@Override public String toString() {
return "Factory[type=" + type.getName() + ",adapter=" + typeAdapter + "]";
}
};
}
如果是自定义的实体类型,用到的TypeAdapters就是ObjectTypeAdapter.FACTORY:
public final class ObjectTypeAdapter extends TypeAdapter<Object> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == Object.class) {
return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
}
return null;
}
};
private final Gson gson;
private ObjectTypeAdapter(Gson gson) {
this.gson = gson;
}
@Override public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
switch (token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<Object>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new StringMap<Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
return in.nextDouble();
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
}
throw new IllegalStateException();
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
if (typeAdapter instanceof ObjectTypeAdapter) {
out.beginObject();
out.endObject();
return;
}
typeAdapter.write(out, value);
}
}
这里如果是BEGIN_ARRAY或者BEGIN_OBJECT类型,他们都有可能有子集合或者子对象,如果是对象,最终用key-value存放在map中,如果是集合就返回集合。接下也有可能是STRING,NUMBER(double,long,int),BOOLEAN(true or false),NULL(null)类型。
这样就创建了对应的工厂,然后create方法的调用才是创建TypeAdapter对象,这里就要回到getAdapter方法的for循环中,最后就是调用上面的read方法进行反序列化。
接下来看TypeAdapter的使用:
大家可以重写他的read和write方法以达到对自己定义的类型的解读,比如从服务器请求回来的一个数据,这个数据需要进行转换成一个对象中的两个字段,这read里面就可以这么操作,比如官方的例子,:
public class PointAdapter extends TypeAdapter<Point> {
public Point read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}
String xy = reader.nextString();
String[] parts = xy.split(",");
int x = Integer.parseInt(parts[0]);
int y = Integer.parseInt(parts[1]);
return new Point(x, y);
}
public void write(JsonWriter writer, Point value) throws IOException {
if (value == null) {
writer.nullValue();
return;
}
String xy = value.getX() + "," + value.getY();
writer.value(xy);
}
}
如果我们已经在read和write中检查 了null的情况,那么我们就使用:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Point.class, new PointAdapter());
Gson gson = builder.create();
如果自己没有手动检查null,就使用:
builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe());
DateTypeAdapter.java
比如你的实体类中有定义的java.util.Date包种的date类型,那么当进行反序列化的时候,会使用DateTypeAdapter来操作你要转换成date类型的字段:
@Override public Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return deserializeToDate(in.nextString());
}
private synchronized Date deserializeToDate(String json) {
try {
return localFormat.parse(json);
} catch (ParseException ignored) {
}
try {
return enUsFormat.parse(json);
} catch (ParseException ignored) {
}
try {
return iso8601Format.parse(json);
} catch (ParseException e) {
throw new JsonSyntaxException(json, e);
}
}
但是这时候如果服务器返回的是空字符,则转换会报异常,因为前面两种转换都捕捉了且不做任何的处理,最后一个用throw new JsonSyntaxException(json, e);来抛出异常来使程序崩溃:
所以最好自己这边在做判断并捕捉异常,如:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@Override
public Date deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
try {
return df.parse(json.getAsString());
} catch (ParseException e) {
return null;
}
}
});
Gson gson = gsonBuilder.create();
这样只要出异常了就捕捉掉并返回null.
TimeTypeAdapter.java
如果实体类中有定义了java.sql.Time中的Time的类型,那么当进行反序列化的时候,会使用TimeTypeAdapter来操作你要转换成Time类型的字段:
private final DateFormat format = new SimpleDateFormat("hh:mm:ss a");
@Override public synchronized Time read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
try {
Date date = format.parse(in.nextString());
return new Time(date.getTime());
} catch (ParseException e) {
throw new JsonSyntaxException(e);
}
}
@Override public synchronized void write(JsonWriter out, Time value) throws IOException {
out.value(value == null ? null : format.format(value));
}
如果实体类中有定义了java.sql.Date中的Date的类型,那么当进行反序列化的时候,会使用SqlDateTypeAdapter来操作你要转换成Date类型的字段:
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
@Override
public synchronized java.sql.Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
try {
final long utilDate = format.parse(in.nextString()).getTime();
return new java.sql.Date(utilDate);
} catch (ParseException e) {
throw new JsonSyntaxException(e);
}
}
@Override
public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException {
out.value(value == null ? null : format.format(value));
}
ArrayTypeAdapter.java
实体中的集合或者数组用该类来过滤。
MapTypeAdapterFactory.java中的Adapter内部类
实体中的map对象用该类来过滤。
TreeTypeAdapter.java
间接调用JsonSerializer和JsonDeserializer实现类的方法。
JsonDeserializer接口的使用:
默认只有一个DefaultDateTypeAdapter类实现了该接口,该类主要是在设置了以下三个方法的时候才会有效果:
public GsonBuilder setDateFormat(String pattern)
public GsonBuilder setDateFormat(int style)
public GsonBuilder setDateFormat(int dateStyle, int timeStyle)
在下面的方法中可以看出:
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
List<TypeAdapterFactory> factories) {
DefaultDateTypeAdapter dateTypeAdapter;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
} else {
return;
}
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter));
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter));
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter));
}
应用场景:
public class Foo {
Date date;
Date created_at;
public Foo(Date date, Date created_at){
this.date = date;
this.created_at = created_at;
}
@Override
public String toString() {
return "Foo [date=" + date + ", created_at=" + created_at + "]";
}
}
public class FooDeserializer implements JsonDeserializer<Foo> {
public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String a = json.getAsJsonObject().get("date").getAsString();
String b = json.getAsJsonObject().get("created_at").getAsString();
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdfDateWithTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date date, created;
try {
date = sdfDate.parse(a);
created = sdfDateWithTime.parse(b);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return new Foo(date, created);
}
}
即使同是Date类型,也可以进行不同格式的转换(使用TypeAdapter同样可以实现)
如果是集合或者map对象,需要这样写:
map:[[{"x":5,"y":6},"a"],[{"x":8,"y":8},"b"]]
Map<Point, String> retMap = gson.fromJson(s, new TypeToken<Map<Point, String>>() {}.getType());
list:
List<Person> ps = gson.fromJson(str, new TypeToken<List<Person>>(){}.getType());