其他
更优雅的使用Gson解析Json
https://juejin.cn/post/7355800792073469992
implementation 'com.google.code.gson:gson:2.10.1'
}
配置Gson
// 为特定类型注册自定义的序列化器或反序列化器(不支持协变)
.registerTypeAdapter(Boolean::class.java, BooleanTypeAdapter())
// 为特定类型注册自定义的序列化器或反序列化器(支持协变)
.registerTypeHierarchyAdapter(xxxx)
// 注册一个能够为多种类型提供适配器的工厂
.registerTypeAdapterFactory(xxxx)
// 设置长整型(Long)字段的序列化策略,例如将其序列化为字符串而不是数字
.setLongSerializationPolicy(LongSerializationPolicy.STRING)
// 自定义日期/时间字段的序列化格式
.setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
// 设置字段命名策略,以控制字段如何映射到JSON键名(默认不改变命名风格)
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
// 设置自定义的字段命名策略,用于控制字段如何映射到JSON键名
.setFieldNamingStrategy(xxxx)
// 排除具有特定Java修饰符(默认 transient 和 static)的字段
.excludeFieldsWithModifiers(java.lang.reflect.Modifier.TRANSIENT or java.lang.reflect.Modifier.STATIC)
// 设置只序列化和反序列化带有@Expose注解的字段
.excludeFieldsWithoutExposeAnnotation()
// 设置类或字段过滤规则
.setExclusionStrategies(xxxx)
// 设置过滤规则(只适用于序列化)
.addSerializationExclusionStrategy(xxxx)
// 设置过滤规则(只适用于反序列化)
.addDeserializationExclusionStrategy(xxxx)
// 设置版本号,Gson将忽略所有高于此版本号的@Since注解和@Until注解的字段
.setVersion(1.0)
// 启用非基础类型 Map Key
.enableComplexMapKeySerialization()
// 默认情况下,Gson在序列化时会忽略值为null的字段。启用该设置后,Gson将包括值为null的字段
.serializeNulls()
// Gson将以更易读的格式输出JSON字符串,即格式化后的JSON,其中包含换行符和缩进。
.setPrettyPrinting()
.create()
Gson gson = new Gson();
gson.toJson(1); // ==> 1
gson.toJson("abcd"); // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 };
gson.toJson(values); // ==> [1]
// Deserialization
int i = gson.fromJson("1", int.class);
Integer intObj = gson.fromJson("1", Integer.class);
Long longObj = gson.fromJson("1", Long.class);
Boolean boolObj = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String[] strArray = gson.fromJson("[\"abc\"]", String[].class);
Gson中的注解
@SerializedName:指定一个字段在JSON中的名称。常用于Java字段名和JSON键名不一致的情况。 @Expose:标记一个字段是否应该被序列化或反序列化。它用于在序列化/反序列化过程中包含或排除字段。 @Since:指定一个字段自某个版本号之后才被序列化或反序列化。这允许版本控制,可以用于向后兼容。 @Until:指定一个字段在某个版本号之前被序列化或反序列化。它与@Since注解相反,用于版本控制和向后兼容。 @JsonAdapter:指定一个字段使用自定义的序列化器和反序列化器。
// username字段在序列化/反序列化时会使用name作为键名
@SerializedName("name")
val username: String,
// 标记password不参与序列化/反序列化
@Expose
val password: String,
// phoneNumber字段只有在版本号为1.1或更高时才会参与序列化/反序列化
@Since(1.1)
val phoneNumber: String,
// email字段只有在版本号低于1.2时才会参与序列化/反序列化
@Until(1.2)
val email: String,
// 使用自定义的GenderAdapter解析器序列化/反序列化gender字段
@JsonAdapter(GenderAdapter::class)
val gender: Gender,
)
enum class Gender {
MALE,
FEMALE,
UNKNOWN,
}
class GenderAdapter: TypeAdapter<Gender>() {
override fun write(out: JsonWriter, value: Gender) {
when (value) {
Gender.UNKNOWN -> out.nullValue()
Gender.MALE -> out.value("1")
Gender.FEMALE -> out.value("2")
}
}
override fun read(`in`: JsonReader): Gender {
return when (`in`.peek()) {
JsonToken.NULL -> {
`in`.nextNull()
Gender.UNKNOWN
}
JsonToken.NUMBER -> {
when(`in`.nextInt()) {
1 -> Gender.MALE
2 -> Gender.FEMALE
else -> Gender.UNKNOWN
}
}
else -> Gender.UNKNOWN
}
}
}
自定义解析
JsonSerializer 和 JsonDeserializer
JsonSerializer 定义如何将类型T的对象转换成JSON。它只有一个方法serialize(T src, Type typeOfSrc, JsonSerializationContext context),返回一个JsonElement对象。 JsonDeserializer 定义如何将JSON转换回类型T的对象。它只有一个方法deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context),返回一个类型为T的对象。
JsonObject: 表示JSON对象,即一组键值对,其中键是字符串,值可以是任意类型的JsonElement。JsonObject提供了添加、删除和访问这些键值对的方法。 JsonArray: 表示JSON数组,即一个元素列表,这些元素本身可以是任意类型的JsonElement。JsonArray提供了添加、删除和访问这些元素的方法。 JsonPrimitive: 表示JSON的原始数据类型,如字符串、数字、布尔值等。JsonPrimitive封装了这些基本类型的值。 JsonNull: 表示JSON的空值。在Gson中,JsonNull是单例,用于表示值为null的情况。
TypeAdapter
// 自定义序列化过程:
// Gender.UNKNOWN -> null
// Gender.MALE -> "1"
// Gender.FEMALE -> "2"
override fun write(out: JsonWriter, value: Gender) {
when (value) {
Gender.UNKNOWN -> out.nullValue()
Gender.MALE -> out.value("1")
Gender.FEMALE -> out.value("2")
}
}
// 自定义反序列化过程:
// null -> Gender.UNKNOWN
// "1" -> Gender.MALE
// "2" -> Gender.FEMALE
override fun read(`in`: JsonReader): Gender {
return when (`in`.peek()) {
JsonToken.NULL -> {
`in`.nextNull()
Gender.UNKNOWN
}
JsonToken.NUMBER -> {
when(`in`.nextInt()) {
1 -> Gender.MALE
2 -> Gender.FEMALE
else -> Gender.UNKNOWN
}
}
else -> Gender.UNKNOWN
}
}
}
TypeAdapter 和 JsonSerializer/JsonDeserializer 的区别
使用场景: JsonSerializer和JsonDeserializer通常用于更简单的场景,当你只需要定制某个类型的序列化或反序列化行为时。TypeAdapter用于更复杂或性能敏感的场景,提供了完全控制序列化和反序列化过程的能力。 性能: TypeAdapter通常比JsonSerializer和JsonDeserializer更高效,因为它避免了中间JsonElement的创建和解析。 灵活性: TypeAdapter提供了对序列化和反序列化过程的完全控制,而JsonSerializer和JsonDeserializer则在某种程度上受限于Gson的序列化和反序列化框架。
List<TypeAdapterFactory> factories = new ArrayList<>();
// 内置类型的适配器,不可覆盖
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.getFactory(objectToNumberStrategy));
// 忽略的字段、类型适配器
factories.add(excluder);
// 用户自定义的适配器
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(NumberTypeAdapter.getFactory(numberToNumberStrategy));
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.newFactory(LazilyParsedNumber.class, TypeAdapters.LAZILY_PARSED_NUMBER));
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);
if (SqlTypesSupport.SUPPORTS_SQL_TYPES) {
factories.add(SqlTypesSupport.TIME_FACTORY);
factories.add(SqlTypesSupport.DATE_FACTORY);
factories.add(SqlTypesSupport.TIMESTAMP_FACTORY);
}
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// map、集合类型适配器
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
// JavaBean类型适配器
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory, reflectionFilters));
基础数据类型适配器 map、集合等容器类型适配器 枚举类型适配器 JavaBean类型适配器
找到合适的类型适配器
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 1.检查传入的TypeToken参数是否为null,若为null则抛出异常。
Objects.requireNonNull(type, "type must not be null");
// 2.从类型缓存typeTokenCache中尝试获取该类型的适配器,如果缓存中存在,则直接返回。
TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
@SuppressWarnings("unchecked")
TypeAdapter<T> adapter = (TypeAdapter<T>) cached;
return adapter;
}
// 3.从线程本地缓存threadLocalAdapterResults中获取当前线程的适配器请求记录,如果不存在则创建一个新的HashMap,并将其设置到线程本地缓存中。
Map<TypeToken<?>, TypeAdapter<?>> threadCalls = threadLocalAdapterResults.get();
boolean isInitialAdapterRequest = false;
if (threadCalls == null) {
threadCalls = new HashMap<>();
threadLocalAdapterResults.set(threadCalls);
isInitialAdapterRequest = true;
} else {
// 在线程本地缓存中查找当前类型是否有适配器,如果存在则直接返回该适配器。
@SuppressWarnings("unchecked")
TypeAdapter<T> ongoingCall = (TypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
}
TypeAdapter<T> candidate = null;
try {
// 4.创建一个FutureTypeAdapter对象,并将其设置为当前类型的适配器请求记录,存入threadLocalAdapterResults
FutureTypeAdapter<T> call = new FutureTypeAdapter<>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
// 5.遍历TypeAdapterFactory工厂,尝试为当前类型创建适配器,若成功创建,则将该适配器设置给FutureTypeAdapter对象,并替换线程本地缓存中的适配器请求记录。
candidate = factory.create(this, type);
if (candidate != null) {
call.setDelegate(candidate);
threadCalls.put(type, candidate);
break;
}
}
} finally {
if (isInitialAdapterRequest) {
threadLocalAdapterResults.remove();
}
}
if (candidate == null) {
// 6.没有找到能够创建适配器的工厂,则抛出IllegalArgumentException异常。
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
}
if (isInitialAdapterRequest) {
// 7.当前线程首次请求适配器,则将线程本地缓存中的适配器发布到全局缓存typeTokenCache中。
typeTokenCache.putAll(threadCalls);
}
return candidate;
}
Gson解析基础数据类型
@Override
public Boolean read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
} else if (peek == JsonToken.STRING) {
// GSON 1.7版本后支持将String解析成boolean类型
return Boolean.parseBoolean(in.nextString());
}
return in.nextBoolean();
}
@Override
public void write(JsonWriter out, Boolean value) throws IOException {
out.value(value);
}
};
Gson解析map和集合
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
Class<? super T> rawType = typeToken.getRawType();
if (!Collection.class.isAssignableFrom(rawType)) {
// 判断传入类型是否为集合类型,如果不是则返回null
return null;
}
// 获取集合元素的类型
Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
// 使用gson.getAdapter()方法获取该元素类型的适配器。
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);
// 创建并返回对应的TypeAdapter
@SuppressWarnings({"unchecked", "rawtypes"})
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
return result;
}
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private final ObjectConstructor<? extends Collection<E>> constructor;
public Adapter(Gson context, Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<>(context, elementTypeAdapter, elementType);
this.constructor = constructor;
}
@Override public Collection<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 通过constructor.construct()创建集合实例
Collection<E> collection = constructor.construct();
// 消费json字符串中的'['
in.beginArray();
while (in.hasNext()) {
// 调用元素TypeAdapter.read(in)生成元素实例
E instance = elementTypeAdapter.read(in);
// 加入集合
collection.add(instance);
}
// 消费json字符串中的']'
in.endArray();
// 返回集合实例
return collection;
}
@Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
if (collection == null) {
out.nullValue();
return;
}
// 生成json字符串中的'['
out.beginArray();
// 遍历集合,调用子元素的TypeAdapter.write序列化子元素
for (E element : collection) {
elementTypeAdapter.write(out, element);
}
// 生成json字符串中的']'
out.endArray();
}
}
Gson解析枚举类型
private final Map<String, T> nameToConstant = new HashMap<>();
private final Map<String, T> stringToConstant = new HashMap<>();
private final Map<T, String> constantToName = new HashMap<>();
public EnumTypeAdapter(final Class<T> classOfT) {
try {
// 使用反射查找枚举常量,以解决混淆类名称的不匹配问题
// 通过访问控制器以特权上下文运行代码,并获取类的声明字段,筛选出枚举常量字段
Field[] constantFields = AccessController.doPrivileged(new PrivilegedAction<Field[]>() {
@Override public Field[] run() {
Field[] fields = classOfT.getDeclaredFields();
ArrayList<Field> constantFieldsList = new ArrayList<>(fields.length);
for (Field f : fields) {
if (f.isEnumConstant()) {
constantFieldsList.add(f);
}
}
Field[] constantFields = constantFieldsList.toArray(new Field[0]);
// 将字段设置为可访问
AccessibleObject.setAccessible(constantFields, true);
return constantFields;
}
});
// 遍历枚举常量字段,并构三个关键的map结构表:
// 1.名称 -> 枚举常量 表 nameToConstant
// 1.字符串 -> 枚举常量 表 stringToConstant
// 3.枚举常量 -> 名称 表 constantToName
for (Field constantField : constantFields) {
@SuppressWarnings("unchecked")
T constant = (T)(constantField.get(null));
String name = constant.name();
String toStringVal = constant.toString();
SerializedName annotation = constantField.getAnnotation(SerializedName.class);
if (annotation != null) {
name = annotation.value();
for (String alternate : annotation.alternate()) {
// 字段上有@SerializedName注解,则使用注解的值作为名称
nameToConstant.put(alternate, constant);
}
}
nameToConstant.put(name, constant);
stringToConstant.put(toStringVal, constant);
constantToName.put(constant, name);
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
@Override public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
String key = in.nextString();
// 根据名称获取枚举常量
T constant = nameToConstant.get(key);
return (constant == null) ? stringToConstant.get(key) : constant;
}
@Override public void write(JsonWriter out, T value) throws IOException {
// 根据常量获取名称
out.value(value == null ? null : constantToName.get(value));
}
}
Gson解析Java Bean
Class<? super T> raw = type.getRawType();
// Object类型,返回null
if (!Object.class.isAssignableFrom(raw)) {
return null; // it's a primitive!
}
// 根据反射过滤器的配置,判断是否允许使用反射来访问该类型字段
FilterResult filterResult =
ReflectionAccessFilterHelper.getFilterResult(reflectionFilters, raw);
if (filterResult == FilterResult.BLOCK_ALL) {
// 不允许,抛出 JsonIOException 异常
throw new JsonIOException(
"ReflectionAccessFilter does not permit using reflection for " + raw
+ ". Register a TypeAdapter for this type or adjust the access filter.");
}
boolean blockInaccessible = filterResult == FilterResult.BLOCK_INACCESSIBLE;
// 如果为Java记录(Record)类型,使用RecordAdapter来处理解析工作
if (ReflectionHelper.isRecord(raw)) {
@SuppressWarnings("unchecked")
TypeAdapter<T> adapter = (TypeAdapter<T>) new RecordAdapter<>(raw,
getBoundFields(gson, type, raw, blockInaccessible, true), blockInaccessible);
return adapter;
}
// 根据该类型的构造函数和字段信息,创建FieldReflectionAdapter实例,并返回该实例作为TypeAdapter的实现
ObjectConstructor<T> constructor = constructorConstructor.get(type);
return new FieldReflectionAdapter<>(constructor, getBoundFields(gson, type, raw, blockInaccessible, false));
}
根据传入的类型是否为Java记录类型返回不同的TypeAdapter。Java记录(Record)类型,使用RecordAdapter来处理解析工作;反之使用FieldReflectionAdapter处理。 无论是RecordAdapter还是FieldReflectionAdapter,都会通过getBoundFields()方法生成一个用以表示字段名和绑定字段(serializeName - boundFiled)的映射关系的Map对象。
final Map<String, BoundField> boundFields;
Adapter(Map<String, BoundField> boundFields) {
this.boundFields = boundFields;
}
@Override
public void write(JsonWriter out, T value) throws IOException {
// value为null,输出null
if (value == null) {
out.nullValue();
return;
}
// 生成json字符串"{"
out.beginObject();
try {
// 遍历boundFields中的所有字段,调用boundField.write()方法将字段的值序列化为JSON格式并输出
for (BoundField boundField : boundFields.values()) {
boundField.write(out, value);
}
} catch (IllegalAccessException e) {
throw ReflectionHelper.createExceptionForUnexpectedIllegalAccess(e);
}
// 生成json字符串"}"
out.endObject();
}
@Override
public T read(JsonReader in) throws IOException {
// null 值校验
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 创建一个accumulator对象来存储字段的值
A accumulator = createAccumulator();
try {
// 消费json字符串"{"
in.beginObject();
// 遍历JSON的所有字段,若字段存在于boundFields中且标记为可反序列化
// 则调用readField()方法将JSON字段的值反序列化为对应的字段值,并存储到accumulator中
while (in.hasNext()) {
String name = in.nextName();
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
} else {
readField(accumulator, in, field);
}
}
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw ReflectionHelper.createExceptionForUnexpectedIllegalAccess(e);
}
// 消费json字符串"}"
in.endObject();
// 将accumulator转换为目标对象的实例并返回
return finalize(accumulator);
}
/** 用于创建用于存储字段值的中间对象 */
abstract A createAccumulator();
/**
* 用于将JSON字段的值反序列化为对应的字段值,并存储到中间对象中
*/
abstract void readField(A accumulator, JsonReader in, BoundField field)
throws IllegalAccessException, IOException;
/** 用于将中间对象转换为目标对象的实例 */
abstract T finalize(A accumulator);
}
Gson如何创建对象?
基础类型、以及基础类型的包装类型等由Gson提供的TypeAdapter通过 new 关键字创建; 枚举类型在EnumTypeAdapter中只是通过枚举名称切换不同的枚举常量,不涉及对象的创建; 集合和map等容器类型通过Gson内置的对象创建工厂,调用 new 关键字进行创建; Java Bean对象的创建比较复杂,分为3种情况,优先级由上到下依次降低: 开发者定义了对象创建工厂InstanceCreator,则使用该工厂创建; 存在默认的无参构造函数,通过反射构造函数创建; 使用Unsafe API 创建。
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
// 1.获取TypeToken对应的类型(Type)和原始类型(Class<? super T>)
final Type type = typeToken.getType();
Class<? super T> rawType = typeToken.getRawType();
// 2.从instanceCreators中根据类型(Type)获取对应的实例创建器(InstanceCreator)
// 如果存在,则创建并返回一个新的对象构造器,该构造器使用该实例创建器来创建对象
final InstanceCreator<T> typeCreator = (InstanceCreator)this.instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor<T>() {
public T construct() {
return typeCreator.createInstance(type);
}
};
} else {
// 3.如果步骤2中没有获取到实例创建器,则尝试根据原始类型(rawType)从instanceCreators中获取实例创建器
// 如果存在,则创建并返回一个新的对象构造器,该构造器使用该实例创建器来创建对象。
final InstanceCreator<T> rawTypeCreator = (InstanceCreator)this.instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
public T construct() {
return rawTypeCreator.createInstance(type);
}
};
} else {
// 4.如果步骤2和步骤3都没有获取到实例创建器,则尝试调用newDefaultConstructor方法创建一个默认构造器,如果存在,则返回该构造器(无参构造函数)
ObjectConstructor<T> defaultConstructor = this.newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
} else {
// 5.如果步骤4中没有创建到默认构造器,则尝试调用newDefaultImplementationConstructor方法创建一个默认实现构造器,如果存在,则返回该构造器(容器类型)
ObjectConstructor<T> defaultImplementation = this.newDefaultImplementationConstructor(type, rawType);
// 6.如果步骤5中没有创建到默认实现构造器,则尝试调用newUnsafeAllocator方法创建一个不安全的分配器构造器,最后返回该构造器(Unsafe)
return defaultImplementation != null ? defaultImplementation : this.newUnsafeAllocator(type, rawType);
}
}
}
}
默认值丢失; Kotlin 非空类型失效; 初始化块可能不会正常执行;
正确的配置Gson
注意null值
不区分大小写的枚举反序列化
合理设置FieldNamingPolicy
合理定义字段类型
val id: Int,
val name: String,
val price: Double,
val type: String,
) {
companion object {
public const val GOOD_TYPE_FRESH = "fresh"
public const val GOOD_TYPE_BOOK = "book"
public const val GOOD_TYPE_FOOD = "food"
}
}
val id: Int,
val name: String,
val price: Double,
val type: GoodType,
)
enum class GoodType {
@SerializedName("fresh")FRESH,
@SerializedName("book")BOOK,
@SerializedName("food")FOOD,
}
巧用TypeAdapter
结合自身产品服务端返回字段的规范合理使用TypeAdapter
val id: Int,
val name: String,
val price: Double,
val type: GoodType,
// 是否为热销商品,1代表热销商品
val isHot: Int,
) {
fun isHot(): Boolean {
return isHot == 1
}
}
override fun write(out: JsonWriter, value: Boolean) {
out.value(value)
}
override fun read(`in`: JsonReader): Boolean? {
return when (`in`.peek()) {
JsonToken.NULL -> {
`in`.nextNull()
null
}
JsonToken.STRING -> {
java.lang.Boolean.parseBoolean(`in`.nextString())
}
// 对数字类型做解析,1为true,其余为false
JsonToken.NUMBER -> {
`in`.nextInt() == 1
}
else -> `in`.nextBoolean()
}
}
}
.registerTypeAdapter(Boolean::class.java, BooleanTypeAdapter())
.create()
val id: Int,
val name: String,
val price: Double,
val type: GoodType,
val isHot: Boolean,
)
结合平台特性合理使用TypeAdapter
val id: Int,
val name: String,
val price: Double,
val type: GoodType,
val isHot: Boolean,
val bgColor: String,
)
// 使用时,需要将颜色字符串通过Color.parseColor方法解析成Android平台的色值Int类型I
var bgColor: Int
try {
bgColor = Color.parseColor(good.bgColor)
} catch (e: Exception) {
bgColor = Color.WHITE
}
view.setBackgroundColor(bgColor)
override fun write(out: JsonWriter, value: Int?) {
if (value == null) {
out.nullValue()
} else {
// 将Int颜色值转换为16进制字符串
val colorStr = "#${Integer.toHexString(value).toUpperCase()}"
out.value(colorStr)
}
}
override fun read(`in`: JsonReader): Int? {
if (`in`.peek() == JsonToken.NULL) {
`in`.nextNull()
return null
}
// 从JSON读取字符串并转换为Int颜色值
val colorStr = `in`.nextString()
return try {
// 使用Android的Color类来解析16进制颜色字符串
Color.parseColor(colorStr)
} catch (e: IllegalArgumentException) {
null
}
}
}
val id: Int,
val name: String,
val price: Double,
val type: GoodType,
val isHot: Boolean,
@JsonAdapter(ColorTypeAdapter::class)
val bgColor: String,
)
// 使用时,直接使用bgColor,无需手动解析
view.setBackgroundColor(bgColor)