Gson提供了
fromJson()
和toJson()
两个直接用于解析和生成的方法。
fromJson()
实现反序列化
toJson()
实现了序列化。
-
Gson的基本用法
基本数据类型的解析(反序列化)
Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class); //99.99
boolean b = gson.fromJson("true", boolean.class); // true
String str = gson.fromJson("String", String.class); // String
请注意
,第2.3行的内容
基本数据类型的生成(序列化)
Gson gson = new Gson();
String jsonNumber = gson.toJson(100); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
POJO类的生成与解析(就是Android中使用的model类)
public class User {
public String name;
public int age;
}
数据类型的生成
Gson gson = new Gson();
User user = new User("abc",24);
String jsonObject = gson.toJson(user); // log输出的结果是:{"name":"abc","age":24}
数据类型的解析
Gson gson = new Gson();
String jsonString = "{\"name\":\"abc\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);
-
Gson的容错机制
之前没有发现,正常我们开发过程中使用的model的每一个字段的基本类型都是按照后台设计好的api式样书进行的,是int,后台就应该返回int,是String就应该返回String。但是调皮的后台有时候也不会让你这么顺心,假如你定义一个int,后台给你返回一个String类型的
123
、null
、“”
、abc
,这样的数据会怎么样?
项目使用的框架是springframework,在RestAAService.class里面有这样的代码
@Rest(
converters = {GsonHttpMessageConverter.class, FormHttpMessageConverter.class, StringHttpMessageConverter.class},
interceptors = {AppRestInterceptor.class},
responseErrorHandler = AppResponseErrorHandler.class)
public interface CKRestAAService extends RestClientErrorHandling {
...
}
注意这个GsonHttpMessageConverter.class,查看源码,反序列化
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
Reader json = new InputStreamReader(inputMessage.getBody(), getCharset(inputMessage.getHeaders()));
try {
Type typeOfT = getType();
if (typeOfT != null) {
return this.gson.fromJson(json, typeOfT);
} else {
return this.gson.fromJson(json, clazz); // 这两行的调用的Gson方法是一样的
}
} catch (JsonSyntaxException ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
} catch (JsonIOException ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
} catch (JsonParseException ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
}
}
Gson.class
在Gson的初始化里面
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
List<TypeAdapterFactory> typeAdapterFactories) {
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.excluder = excluder;
this.fieldNamingStrategy = fieldNamingStrategy;
this.serializeNulls = serializeNulls;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
this.lenient = lenient;
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// 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);
TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
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.ATOMIC_INTEGER_FACTORY);
factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_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.CURRENCY_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.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
反序列化的方法
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;
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
T object = typeAdapter.read(reader); // 最终使用的是 TypeAdapter对象来处理这个reader。
return object;
} 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);
}
}
再看下 TypeAdapters.class,在这类里面会定义很多个TypeAdapterFactory,其中摘取 int类型的
public static final TypeAdapter<Number> NUMBER = new TypeAdapter<Number>() {
@Override
public Number read(JsonReader in) throws IOException {
JsonToken jsonToken = in.peek(); // Returns the type of the next token without consuming it.
switch (jsonToken) {
case NULL:
in.nextNull();
return null;
case NUMBER:
case STRING:
return new LazilyParsedNumber(in.nextString()); // 注意这行
default:
throw new JsonSyntaxException("Expecting number, got: " + jsonToken);
}
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};
LazilyParsedNumber.class
/** @param value must not be null */
public LazilyParsedNumber(String value) {
this.value = value;
}
@Override
public int intValue() {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
try {
return (int) Long.parseLong(value);
} catch (NumberFormatException nfe) {
return new BigDecimal(value).intValue();
}
}
}
在这就能看到,当输入的内容是String的时候,就会说尝试将String转换成 int,但是如果是 非数字 字符串就会转换失败,出现异常。
在摘几个例子:
如果定义的是String类型,返回的是boolean类型,那么就会将true
或者false
转换成 "true"
or "false"
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
/* coerce booleans to strings for backwards compatibility */
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean());
}
return in.nextString();
}
@Override
public void write(JsonWriter out, String value) throws IOException {
out.value(value);
}
};
以上,如有错误请指正
お願いいたします。
网友评论