1 概述
Json(JavaScript Object Notation)是一种可读性和通用性都非常强的轻量级的数据交换格式,一开始是JavaScript中广泛使用,到了后面流传几乎所有语言都有相应的使用API,所以它已是行业公认的标准。与JavaScript等的动态类型语言一起使用时非常方便,只要将数据转换成字符串,便可以在函数之间轻松地传递字符串进行数据传递。但是在像C++、Java等的静态类型语言序列化数据时,Json的效率表现仅一般,而且还需要编写较多代码来访问数据和转化成类对象。
Gson是Google开发的一个用于生成和解析Json数据格式的Java开源库。它的特点是可将Java类对象序列化为其Json字符串,也可将Json字符串反序列化成等效的Java类对象。
2 Json数据结构
Object:表示对象,使用大括号{}包含的键值对结构,Key必须是String类型,value为任何基本类型或者数组。
Array:表示数组,使用中括号[]包含一或多组Object,组间用逗号分隔。
例如:
{
"id": 1001,
"name": "子云心",
"phones": [
{
"number": "12345678910",
"type": "MOBILE"
},
{
"number": "0000-1234567",
"type": "HOME"
}
],
"verified": true
}
3 Android中Json的使用
String jsonText = "{\"id\":1001,\"name\":\"子云心\",\"phones\":[{\"number\":\"12345678910\",\"type\":\"MOBILE\"},{\"number\":\"0000-1234567\",\"type\":\"HOME\"}],\"verified\":true}";
Student student = new Student();
try {
JSONObject jsonObject = new JSONObject(jsonText);
if (jsonObject.has("id")) {
int id = jsonObject.getInt("id");
student.setId(id);
}
if (jsonObject.has("name")) {
String name = jsonObject.getString("name");
student.setName(name);
}
if (jsonObject.has("verified")) {
boolean verified = jsonObject.getBoolean("verified");
student.setVerified(verified);
}
if (jsonObject.has("phones")) {
List<Student.Phone> phones = new ArrayList<>();
JSONArray jsonArray = jsonObject.getJSONArray("phones");
for (int i = 0; i < jsonArray.length(); i++) {
Student.Phone phone = new Student.Phone();
JSONObject phoneJsonObject = jsonArray.getJSONObject(i);
if (phoneJsonObject.has("number")) {
String number = phoneJsonObject.getString("number");
phone.setNumber(number);
}
if (phoneJsonObject.has("type")) {
String type = phoneJsonObject.getString("type");
phone.setType(type);
}
phones.add(phone);
}
student.setPhones(phones);
}
} catch (JSONException e) {
e.printStackTrace();
}
public class Student {
private int id;
private String name;
private boolean verified;
private List<Phone> phones;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
public boolean isVerified() {
return verified;
}
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
static class Phone {
private String number;
private String type;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
}
4 使用Gson
4.1 依赖
Gson库地址:https://github.com/google/gson/,代码中使用需要先进行库的远程依赖:
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
}
4.2 fromJson和toJson
继续使用上方Student示例,用Gson的代码是这样:
String jsonText = "{\"id\":1001,\"name\":\"子云心\",\"phones\":[{\"number\":\"12345678910\",\"type\":\"MOBILE\"},{\"number\":\"0000-1234567\",\"type\":\"HOME\"}],\"verified\":true}";
Gson gson = new Gson();
Student student = gson.fromJson(jsonText, Student.class);
String jsonText2 =gson.toJson(student);
Gson类提供了关键方式 fromJson(String,Class<T>) 和 toJson(Object, Type) 进行Json转对象和对象转Json。
注意:一般类对象,toJson(Object, Type)的第二个参数是可以忽略,但是如果需要序列化的对象是一个泛型对象或者集合类型对象,则一定要传入Type。例如:
Type shapeType = new TypeToken<Student>() {}.getType();
String jsonText3 =gson.toJson(student, shapeType);
Type listType = new TypeToken<List<String>>() {}.getType();
String jsonText4 =gson.toJson(student, listType);
4.3 Gson对象创建
使用Gson就是需要实例化一个Gson类对象,如上述代码可以简单地使用new Gson();的方式进行默认配置的创建,也可以通过Gson类提供的建造者模式的创建方式,例如:
Gson gson = new Gson();
Gson gson2 = new GsonBuilder()
??????? .setPrettyPrinting()
??????? .serializeNulls()
??????? .setVersion(1.0)
??????? .setDateFormat("yyyy-MM-dd HH:mm:ss")
??????? .registerTypeAdapter(Student.class, new StudentAdapter())
??????? .excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
setPrettyPrinting
用于设置转成Json字符串数据是带格式化的,即带空格缩进。
serializeNulls
当对象字段为null时默认转成Json时是忽略的,而serializeNulls用于设置当对象字段为null时,转成Json仍保留字段名,其值为null,如:"name": null。
setVersion
用于设置Json版本值,例如上述设置了1.0的值后,当遇到带类中 @Since(1.1)注解的字段时(1.1版本>1.0版本),转换成Json后会忽略该字段。
setDateFormat
用于设置转成Json时日期时间的格式。
registerTypeAdapte
注册自定义的适配器(下方细讲)。
excludeFieldsWithModifiers
类对象在转成Json时会默认忽略类中的静态字段,而如果希望保留可以像上述设置.excludeFieldsWithModifiers(Modifier.TRANSIENT)。
4.4 常用注解
4.4.1 @Since
结合GsonBuilder.setVersion方法一起使用。例如setVersion设置了1.0的值后,当遇到带类中 @Since(1.1)注解的字段时(1.1版本>1.0版本),转换成Json后会忽略该字段。
4.4.2 @SerializedName
用于给类中字段更名,例如
@SerializedName("fullName")
private String name; // 支持更名后的fullName
@SerializedName(value = "name", alternate = "fullName")
private String name; // 新旧字段名称一起支持
4.4.3 @Expose
用于序列化或反序列化时忽略字段,例如:
@Expose()
private String name; // 参与序列化/反序列化
@Expose(serialize = false, deserialize = false)
private String name; // 不参与序列化,也不参与反序列化
@Expose(serialize = false)
private String name; // 只参与反序列化
@Expose(deserialize = false)
private String name; // 只参与序列化
忽略某个字段序列化/反序列化还可以直接使用transient关键字 例如:
String transient name; //不参与序列化/反序列化
4.5 树模型
Gson可以支持构建了一个JsonObject节点树。 这是一种灵活的方法,类似于XML的DOM解析器,使用上类似Java中Json的使用里面的 JSONObject的用法。
String jsonText = "{\"id\":1001,\"name\":\"子云心\",\"phones\":[{\"number\":\"12345678910\",\"type\":\"MOBILE\"},{\"number\":\"0000-1234567\",\"type\":\"HOME\"}],\"verified\":true}";
Student student = read(jsonText);
public Student read(String jsonText) {
Student student = new Student();
JsonElement rootNode = JsonParser.parseString(jsonText);
if (!rootNode.isJsonObject()) {
return student;
}
JsonObject jsonObject = rootNode.getAsJsonObject();
if(jsonObject.has("id")) {
int id = jsonObject.get("id").getAsInt();
student.setId(id);
}
if(jsonObject.has("name")) {
String name = jsonObject.get("name").getAsString();
student.setName(name);
}
if (jsonObject.has("phones")) {
List<Student.Phone> phones = new ArrayList<>();
JsonArray jsonArray = jsonObject.getAsJsonArray("phones");
for (int i = 0; i < jsonArray.size(); i++) {
Student.Phone phone = new Student.Phone();
JsonObject phoneJsonObject = jsonArray.get(i).getAsJsonObject();
if (phoneJsonObject.has("number")) {
String number = phoneJsonObject.get("number").getAsString();
phone.setNumber(number);
}
if (phoneJsonObject.has("type")) {
String type = phoneJsonObject.get("type").getAsString();
phone.setType(type);
}
phones.add(phone);
}
student.setPhones(phones);
}
if (jsonObject.has("verified")) {
boolean verified = jsonObject.get("verified").getAsBoolean();
student.setVerified(verified);
}
return student;
}
4.6 数据流
GSON数据流的方式读取Json数据是最低开销,并且读/写速度是非常快的方法,它类似于用于XML的SAX解析器。
String jsonText = "{\"id\":1001,\"name\":\"子云心\",\"phones\":[{\"number\":\"12345678910\",\"type\":\"MOBILE\"},{\"number\":\"0000-1234567\",\"type\":\"HOME\"}],\"verified\":true}";
Student student = null;
try {
student = read(jsonText);
} catch (IOException e) {
e.printStackTrace();
}
try {
String jsonText2 = write(student);
} catch (IOException e) {
e.printStackTrace();
}
public Student read(String jsonText) throws IOException {
JsonReader reader = new JsonReader(new StringReader(jsonText));
Student student = new Student();
String fieldName = null;
reader.beginObject();
while (reader.hasNext()) {
JsonToken token = reader.peek();
if (token.equals(JsonToken.NAME)) {
fieldName = reader.nextName();
}
if ("id".equals(fieldName)) {
token = reader.peek();
if (token.equals(JsonToken.NUMBER)) {
int id = reader.nextInt();
student.setId(id);
}
continue;
}
if ("name".equals(fieldName)) {
token = reader.peek();
if (token.equals(JsonToken.STRING)) {
String name = reader.nextString();
student.setName(name);
}
continue;
}
if ("phones".equals(fieldName)) {
List<Student.Phone> phones = null;
token = reader.peek();
if (token.equals(JsonToken.BEGIN_ARRAY)) {
reader.beginArray();
phones = new ArrayList();
}
Student.Phone phone = null;
while (!token.equals(JsonToken.END_ARRAY)) {
token = reader.peek();
if (token.equals(JsonToken.BEGIN_OBJECT)) {
reader.beginObject();
phone = new Student.Phone();
continue;
}
if (token.equals(JsonToken.NAME)) {
fieldName = reader.nextName();
if ("number".equals(fieldName)) {
token = reader.peek();
if (token.equals(JsonToken.STRING)) {
String number = reader.nextString();
phone.setNumber(number);
}
continue;
}
if ("type".equals(fieldName)) {
token = reader.peek();
if (token.equals(JsonToken.STRING)) {
String type = reader.nextString();
phone.setType(type);
}
continue;
}
}
if (token.equals(JsonToken.END_OBJECT)) {
phones.add(phone);
reader.endObject();
continue;
}
}
student.setPhones(phones);
reader.endArray();
continue;
}
if ("verified".equals(fieldName)) {
token = reader.peek();
if (token.equals(JsonToken.BOOLEAN)) {
boolean verified = reader.nextBoolean();
student.setVerified(verified);
}
continue;
}
}
reader.endObject();
return student;
}
public String write(Student student) throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
writer.beginObject();
writer.name("id");
writer.value(student.getId());
writer.name("name");
writer.value(student.getName());
writer.name("phones");
writer.beginArray();
for (int i = 0; i < student.getPhones().size(); i++) {
writer.beginObject();
writer.name("number");
writer.value(student.getPhones().get(i).getNumber());
writer.name("type");
writer.value(student.getPhones().get(i).getType());
writer.endObject();
}
writer.endArray();
writer.name("verified");
writer.value(student.isVerified());
writer.endObject();
return stringWriter.toString();
}
4.7 自定义适配器进行解析
Gson提供了两种自定义解析的方法:继承TypeAdapter类 和 实现JsonSerializer/JsonDeserializer接口
4.7.1继承TypeAdapter类
通过继承TypeAdapter类并传递目标类型的对象来创建自定义适配器。 重写它的read和write方法分别执行自定义的反序列化和序列化。
String jsonText = "{\"id\":1001,\"name\":\"子云心\",\"phones\":[{\"number\":\"12345678910\",\"type\":\"MOBILE\"},{\"number\":\"0000-1234567\",\"type\":\"HOME\"}],\"verified\":true}";
Gson gson = new GsonBuilder()
.registerTypeAdapter(Student.class, new StudentAdapter())
.create();
Student student = gson.fromJson(jsonText, Student.class);
String jsonText2 =gson.toJson(student);
public class StudentAdapter extends TypeAdapter<Student> {
@Override
public Student read(JsonReader reader) throws IOException {
Student student = new Student();
String fieldName = null;
reader.beginObject();
// ……
// 中间跟4.6数据流 中read方法代码一样
reader.endObject();
return student;
}
@Override
public void write(JsonWriter writer, Student student) throws IOException {
writer.beginObject();
// ……
// 中间跟4.6数据流 中write方法代码一样
writer.endObject();
}
}
4.7.2实现JsonSerializer/JsonDeserializer接口
实现JsonSerializer和JsonDeserializer接口,并重写它们对应的serialize和deserialize方法同样可以实现自定义反序列化和序列。而且JsonSerializer和JsonDeserializer接口是不必同时实现的,这种方式也增加了其灵活性,不过代价就是解析效率也会有所降低,因为JsonElement最终也是会转成JsonReader进行序列化和反序列化。
public class StudentDeserializer implements JsonDeserializer<Student> {
@Override
public Student deserialize(JsonElement rootNode, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Student student = new Student();
if (!rootNode.isJsonObject()) {
return student;
}
JsonObject jsonObject = rootNode.getAsJsonObject();
// ……
// 中间跟4.5树模型 中read方法代码一样
return student;
}
}
public class StudentSerializer implements JsonSerializer<Student> {
@Override
public JsonElement serialize(Student student, Type typeOfSrc, JsonSerializationContext context) {
try {
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
writer.beginObject();
// ……
// 中间跟4.6数据流 中write方法代码一样
writer.endObject();
String jsonText = stringWriter.toString();
JsonElement rootNode = JsonParser.parseString(jsonText);
return rootNode;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
String jsonText = "{\"id\":1001,\"name\":\"子云心\",\"phones\":[{\"number\":\"12345678910\",\"type\":\"MOBILE\"},{\"number\":\"0000-1234567\",\"type\":\"HOME\"}],\"verified\":true}";
Gson gson = new GsonBuilder()
.registerTypeAdapter(Student.class, new StudentDeserializer())
.registerTypeAdapter(Student.class, new StudentSerializer())
.create();
Student student = gson.fromJson(jsonText, Student.class);
String jsonText2 =gson.toJson(student);
5 原理
我们从上面自定义适配器进行解析中大概也能知道,Gson的原理其实关键就是TypeAdapter,也是类型适配,如何将Json转成一个类对象和将类对象再转Json。Gson中的TypeAdapter大至可分为3类,分别是:
- 用户自定义类型适配器 –- 通过registerTypeAdapter传入
- 基本平台类型的适配器 – String、Int、Boolean等
- 通用反射类型适配器 –- ReflectiveTypeAdapter
5.1 自定义类型适配器
我们通过registerTypeAdapter方法传入的TypeAdapter类或者传入的JsonSerializer/JsonDeserializer接口最后会被赋值给一个factories变量:
GsonBuilder.java
private final List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
// ……
if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
TypeToken<?> typeToken = TypeToken.get(type);
factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
}
if (typeAdapter instanceof TypeAdapter<?>) {
factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
}
return this;
}
而factories列表最终在构造Gson对象时会被传入其构造函数中去:
public Gson create() {
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(this.factories.size() + this.hierarchyFactories.size() + 3);
factories.addAll(this.factories);
Collections.reverse(factories);
List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>(this.hierarchyFactories);
Collections.reverse(hierarchyFactories);
factories.addAll(hierarchyFactories);
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
return new Gson(excluder, fieldNamingPolicy, instanceCreators,
serializeNulls, complexMapKeySerialization,
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
serializeSpecialFloatingPointValues, longSerializationPolicy,
datePattern, dateStyle, timeStyle,
this.factories, this.hierarchyFactories, factories);
}
5.2 Gson的构造函数
Gson类最多参数的构造函数中最后的factoriesToBeAdded便是刚才通过registerTypeAdapter传入的自定义适配器:
Gson.java
Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
int timeStyle, List<TypeAdapterFactory> builderFactories,
List<TypeAdapterFactory> builderHierarchyFactories,
List<TypeAdapterFactory> factoriesToBeAdded) {
// ……
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);
// registerTypeAdapter方法中传入的自定义的解析器
factories.addAll(factoriesToBeAdded);
// 基本平台类型的类型适配器
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);
// 在最后添加通用的ReflectiveTypeAdapter
factories.add(new ReflectiveTypeAdapterFactory(constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
变量factories是一个TypeAdapterFactory列表,它用于存储不同类型的TypeAdapter工厂。Gson中每一种基本类型都会对应一个TypeAdapter进行适配,而所有我们自定义的类型(即示例中的Student)会由我们自己定义的解析器factoriesToBeAdded或者通用反射解析器ReflectiveTypeAdapter来完成适配。
5.3 基本平台类型的适配器
在Gson构造函数中添加了很多基本平台类型的适配器,基本平台类型的适配器在TypeAdapter类中实现,其中字符串和整型的适配器,其源码如下:
TypeAdapter.java
public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);
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);
}
};
public static final TypeAdapterFactory INTEGER_FACTORY = newFactory(int.class, Integer.class, INTEGER);
public static final TypeAdapter<Number> INTEGER = new TypeAdapter<Number>() {
@Override
public Number read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
try {
return in.nextInt();
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};
5.4 通用反射类型适配器
通用反射类型适配器就是ReflectiveTypeAdapter。因为所有的TypeAdapter都是通过TypeAdapterFactory的create方法进行创建,我们来看看ReflectiveTypeAdapter的create方法:
ReflectiveTypeAdapterFactory.java
@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));
}
方法返回一个Adapter类,Adapter类是ReflectiveTypeAdapterFactory的一个内部类,它继承于TypeAdapter,实现了read和write方法:
public static final class Adapter<T> extends TypeAdapter<T> {
private final ObjectConstructor<T> constructor;
private final Map<String, BoundField> boundFields;
// 构造函数接收对象类型构造器和类型内部的所有字段列表
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
@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对象
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
} else {
// 调用其read方法进行字段赋值
field.read(in, instance);
}
}
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
in.endObject();
return instance;
}
@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();
}
}
Adapter类的构造函数接收两个参数,constructor是类的类型构造器,它是构造Gson时的第3个参数,boundFields是类型内部的所有字段列表,它由getBoundFields方法获取:
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
// ……
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());
// 获取该字段的所有名称,因为当使用了@SerializedName注解时会出现多个名称
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
// 通过createBoundField方法来创建BoundField对象
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;
}
static abstract class BoundField {
final String name;
final boolean serialized;
final boolean deserialized;
protected BoundField(String name, boolean serialized, boolean deserialized) {
this.name = name;
this.serialized = serialized;
this.deserialized = deserialized;
}
abstract boolean writeField(Object value) throws IOException, IllegalAccessException;
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
}
在Adapter类中read方法调用的boundField.read和write方法调用的boundField.write的实现就是在createBoundField方法内:
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
final Gson context, final Field field, final String name,
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
// special casing primitives here saves ~5% on Android...
JsonAdapter annotation = field.getAnnotation(JsonAdapter.class);
TypeAdapter<?> mapped = null;
if (annotation != null) {
mapped = jsonAdapterFactory.getTypeAdapter(constructorConstructor, context, fieldType, annotation);
}
final boolean jsonAdapterPresent = mapped != null;
if (mapped == null) mapped = context.getAdapter(fieldType);
final TypeAdapter<?> typeAdapter = mapped;
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
@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);
}
@Override void read(JsonReader reader, Object value) throws IOException, IllegalAccessException {
// 如果是基础平台类型,直接读取,如果是自定义的类则递归前面的流程
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
// 反射给Field赋值
field.set(value, fieldValue);
}
}
@Override public boolean writeField(Object value) throws IOException, IllegalAccessException {
if (!serialized) return false;
Object fieldValue = field.get(value);
return fieldValue != value; // avoid recursion for example for Throwable.cause
}
};
}
5.5 使用fromJson
我们在使用Student student = gson.fromJson(jsonText, Student.class); 时,最后会调用到Gson类中的fromJson(JsonReader reader, Type typeOfT)方法:
Gson.java
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
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;
}
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
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);
// 调用适配器的read方法进行反序列化
T object = typeAdapter.read(reader);
return object;
} catch (EOFException e) {
……
} finally {
reader.setLenient(oldLenient);
}
}
fromJson方法内关键代码是调用了getAdapter来获取合适的适配器:
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
……
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
// 遍历TypeAdapterFactory列表,并调用其create创建TypeAdapter
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 (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
} finally {
threadCalls.remove(type);
……
}
}
方法内遍历了factories 列表,factories 便是在Gson的构造函数中有通过registerTypeAdapter传入的多个自定义类型适配器、基本平台类型适配器和通用反射类型适配器。再通过调用其create方法,返回非空便是最后合适的适配器。
6 总结
Gson是可以将Java类对象序列化成Json字符串和可将Json字符串反序列化成等效的Java类对象的一个Json解析增强库。内部可通过数据流的形式或者树模式的形式进行Json的解析。在解析过程中根据类型选择合适的类型适配器再结合反射的机制,使用了简短的代码 toJson 和 fromJson 进行序列化和反序列化。
|