irpas技术客

Android序列化(四) 之 Gson_子云心_android gson

网络 8431

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 进行序列化和反序列化。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Android #gson #1 #Object