Android Gson复杂数据结构(如Map、List)的序列化逻辑原理剖析(20)

45 阅读6分钟

码字不易,请大佬们点点关注,谢谢~

一、复杂数据结构序列化概述

1.1 复杂数据结构处理的重要性

在Android开发中,JSON数据往往包含复杂数据结构,如MapList等。Gson作为常用的JSON处理库,其对复杂数据结构的序列化能力至关重要。准确处理这些结构能确保数据在网络传输、本地存储等场景下保持完整的语义和结构,避免数据丢失或格式错乱。

1.2 核心处理流程

Gson对复杂数据结构的序列化主要包含以下步骤:

  1. 类型识别:确定待序列化对象的具体类型(如HashMapArrayList)。
  2. 适配器选择:根据类型从工厂链中匹配对应的TypeAdapter
  3. 递归处理:对于嵌套结构,递归调用序列化逻辑。
  4. JSON输出:通过JsonWriter将数据写入字符流。

1.3 关键组件

涉及的核心组件包括:

  • TypeAdapter:负责具体类型的序列化操作。
  • TypeAdapterFactory:工厂链,用于创建TypeAdapter实例。
  • JsonWriter:底层JSON字符流写入器。
  • 反射机制:处理自定义类和复杂对象图。

二、List类型的序列化原理

2.1 内置List类型适配器工厂

Gson通过CollectionTypeAdapterFactory处理List等集合类型:

public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
    private final ConstructorConstructor constructorConstructor;

    public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
        this.constructorConstructor = constructorConstructor;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Type type = typeToken.getType();
        Class<? super T> rawType = typeToken.getRawType();

        // 检查是否为集合类型(如List、Set等)
        if (!Collection.class.isAssignableFrom(rawType)) {
            return null;
        }

        // 解析集合元素类型
        Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
        TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));

        // 创建集合构造器
        ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);

        // 创建List类型适配器
        return (TypeAdapter<T>) new Adapter<>(
            gson, elementType, elementTypeAdapter, constructor
        );
    }

    private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
        private final TypeAdapter<E> elementTypeAdapter;
        private final ObjectConstructor<? extends Collection<E>> constructor;

        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 {
            // 处理null值
            if (in.peek() == JsonToken.NULL) {
                in.nextNull();
                return null;
            }

            // 创建目标集合实例
            Collection<E> collection = constructor.construct();
            in.beginArray();
            while (in.hasNext()) {
                // 递归读取每个元素
                E instance = elementTypeAdapter.read(in);
                collection.add(instance);
            }
            in.endArray();
            return collection;
        }

        @Override
        public void write(JsonWriter out, Collection<E> collection) throws IOException {
            // 处理null值
            if (collection == null) {
                out.nullValue();
                return;
            }

            // 开始写入JSON数组
            out.beginArray();
            for (E element : collection) {
                // 递归写入每个元素
                elementTypeAdapter.write(out, element);
            }
            out.endArray();
        }
    }
}

2.2 元素类型处理

  1. 基本类型元素:如List<Integer>,使用PrimitiveTypeAdapter直接写入JSON数值。
// 处理List<Integer>的写入逻辑
out.beginArray();
for (Integer element : list) {
    // 直接写入整数值
    out.value(element);
}
out.endArray();
  1. 对象类型元素:如List<User>,递归调用User类型的TypeAdapter
// 处理List<User>的写入逻辑
out.beginArray();
for (User user : list) {
    // 调用User类型适配器的write方法
    userTypeAdapter.write(out, user);
}
out.endArray();

2.3 嵌套List处理

对于嵌套结构如List<List<Integer>>,Gson会递归处理:

  1. 外层List适配器调用内层List适配器。
  2. 内层List适配器处理具体元素。
// 处理List<List<Integer>>的写入逻辑
out.beginArray();
for (List<Integer> innerList : outerList) {
    // 开始写入内层数组
    out.beginArray();
    for (Integer element : innerList) {
        out.value(element);
    }
    out.endArray();
}
out.endArray();

三、Map类型的序列化原理

3.1 内置Map类型适配器工厂

Gson通过MapTypeAdapterFactory处理Map类型:

public final class MapTypeAdapterFactory implements TypeAdapterFactory {
    private final ConstructorConstructor constructorConstructor;

    public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
        this.constructorConstructor = constructorConstructor;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Type type = typeToken.getType();
        Class<? super T> rawType = typeToken.getRawType();

        // 检查是否为Map类型
        if (!Map.class.isAssignableFrom(rawType)) {
            return null;
        }

        // 解析键和值的类型
        Type keyType = $Gson$Types.getTypeParameter(type, Map.class, 0);
        Type valueType = $Gson$Types.getTypeParameter(type, Map.class, 1);

        TypeAdapter<?> keyAdapter = gson.getAdapter(TypeToken.get(keyType));
        TypeAdapter<?> valueAdapter = gson.getAdapter(TypeToken.get(valueType));

        // 创建Map构造器
        ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);

        // 创建Map类型适配器
        return (TypeAdapter<T>) new Adapter<>(
            gson, keyType, keyAdapter, valueType, valueAdapter, constructor
        );
    }

    private static final class Adapter<K, V> extends TypeAdapter<Map<K, V>> {
        private final TypeAdapter<K> keyAdapter;
        private final TypeAdapter<V> valueAdapter;
        private final ObjectConstructor<? extends Map<K, V>> constructor;

        Adapter(Gson context, Type keyType, TypeAdapter<K> keyAdapter,
                Type valueType, TypeAdapter<V> valueAdapter,
                ObjectConstructor<? extends Map<K, V>> constructor) {
            this.keyAdapter = new TypeAdapterRuntimeTypeWrapper<>(
                context, keyAdapter, keyType
            );
            this.valueAdapter = new TypeAdapterRuntimeTypeWrapper<>(
                context, valueAdapter, valueType
            );
            this.constructor = constructor;
        }

        @Override
        public Map<K, V> read(JsonReader in) throws IOException {
            // 处理null值
            if (in.peek() == JsonToken.NULL) {
                in.nextNull();
                return null;
            }

            // 创建目标Map实例
            Map<K, V> map = constructor.construct();
            in.beginObject();
            while (in.hasNext()) {
                // 读取键
                K key = keyAdapter.read(in);
                // 读取值
                V value = valueAdapter.read(in);
                map.put(key, value);
            }
            in.endObject();
            return map;
        }

        @Override
        public void write(JsonWriter out, Map<K, V> map) throws IOException {
            // 处理null值
            if (map == null) {
                out.nullValue();
                return;
            }

            // 开始写入JSON对象
            out.beginObject();
            for (Map.Entry<K, V> entry : map.entrySet()) {
                // 写入键
                keyAdapter.write(out, entry.getKey());
                // 写入值
                valueAdapter.write(out, entry.getValue());
            }
            out.endObject();
        }
    }
}

3.2 键值对处理

  1. 键类型限制:Gson要求Map的键类型必须为基本类型或String,因为JSON的键只能是字符串。
// 写入键值对逻辑
for (Map.Entry<K, V> entry : map.entrySet()) {
    // 将键转换为字符串(如果需要)
    keyAdapter.write(out, entry.getKey());
    valueAdapter.write(out, entry.getValue());
}
  1. 值类型处理:与List类似,根据值的类型递归调用相应的TypeAdapter

3.3 嵌套Map处理

对于Map<String, Map<String, Integer>>这样的嵌套结构:

  1. 外层Map适配器处理键值对。
  2. 内层Map适配器处理子键值对。
// 处理Map<String, Map<String, Integer>>的写入逻辑
out.beginObject();
for (Map.Entry<String, Map<String, Integer>> outerEntry : outerMap.entrySet()) {
    // 写入外层键
    out.name(outerEntry.getKey());
    // 开始写入内层对象
    out.beginObject();
    for (Map.Entry<String, Integer> innerEntry : outerEntry.getValue().entrySet()) {
        out.name(innerEntry.getKey());
        out.value(innerEntry.getValue());
    }
    out.endObject();
}
out.endObject();

四、自定义复杂数据结构的序列化

4.1 自定义TypeAdapter

开发者可通过继承TypeAdapter处理自定义复杂结构:

public class CustomListTypeAdapter<T> extends TypeAdapter<List<T>> {
    private final TypeAdapter<T> elementAdapter;

    public CustomListTypeAdapter(TypeAdapter<T> elementAdapter) {
        this.elementAdapter = elementAdapter;
    }

    @Override
    public List<T> read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        List<T> list = new ArrayList<>();
        in.beginArray();
        while (in.hasNext()) {
            T element = elementAdapter.read(in);
            list.add(element);
        }
        in.endArray();
        return list;
    }

    @Override
    public void write(JsonWriter out, List<T> list) throws IOException {
        if (list == null) {
            out.nullValue();
            return;
        }

        out.beginArray();
        for (T element : list) {
            // 自定义元素处理逻辑
            if (element != null) {
                elementAdapter.write(out, element);
            }
        }
        out.endArray();
    }
}

4.2 注册自定义适配器

通过GsonBuilder注册:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(List.class, new CustomListTypeAdapter<>(gson.getAdapter(Object.class)))
    .create();

4.3 处理特殊需求

例如,为List添加额外元数据:

public class AnnotatedList<T> {
    public int size;
    public List<T> data;
}

public class AnnotatedListTypeAdapter<T> extends TypeAdapter<AnnotatedList<T>> {
    private final TypeAdapter<List<T>> listAdapter;

    public AnnotatedListTypeAdapter(TypeAdapter<List<T>> listAdapter) {
        this.listAdapter = listAdapter;
    }

    @Override
    public AnnotatedList<T> read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        AnnotatedList<T> annotatedList = new AnnotatedList<>();
        in.beginObject();
        while (in.hasNext()) {
            String name = in.nextName();
            if ("size".equals(name)) {
                annotatedList.size = in.nextInt();
            } else if ("data".equals(name)) {
                annotatedList.data = listAdapter.read(in);
            } else {
                in.skipValue();
            }
        }
        in.endObject();
        return annotatedList;
    }

    @Override
    public void write(JsonWriter out, AnnotatedList<T> value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }

        out.beginObject();
        out.name("size").value(value.size);
        out.name("data");
        listAdapter.write(out, value.data);
        out.endObject();
    }
}

五、性能优化与异常处理

5.1 性能优化策略

  1. 减少反射调用:自定义TypeAdapter可避免反射开销。
  2. 缓存适配器:复用TypeAdapter实例,减少创建开销。
  3. 批量处理:对大量数据采用批量写入,减少JsonWriter操作次数。
  4. 避免嵌套过深:过深的嵌套结构会增加递归调用层数,影响性能。

5.2 异常处理机制

  1. 类型不匹配:反序列化时若JSON结构与Java类型不匹配,抛出JsonSyntaxException
// MapTypeAdapterFactory.Adapter的read方法
try {
    K key = keyAdapter.read(in);
    V value = valueAdapter.read(in);
    map.put(key, value);
} catch (IOException e) {
    throw new JsonSyntaxException("Error reading Map entry", e);
}
  1. NullPointerException:处理null值时,遵循Gson的serializeNulls配置。
  2. 循环引用:通过JsonWriter的对象引用跟踪机制避免无限递归。

六、总结与展望

6.1 核心机制总结

Gson对复杂数据结构的序列化通过以下机制实现:

  • 工厂链适配CollectionTypeAdapterFactoryMapTypeAdapterFactory处理标准集合类型。
  • 递归处理:通过递归调用处理嵌套结构。
  • 类型适配:根据元素类型动态选择TypeAdapter
  • 扩展性:支持自定义TypeAdapter处理特殊结构。

6.2 未来发展方向

  1. Kotlin协程支持:在异步场景下优化复杂结构的序列化性能。
  2. 字节码生成:通过编译时生成代码减少反射开销。
  3. 多平台优化:针对不同平台(如Android、JVM)提供定制化处理。
  4. 更智能的类型推断:自动处理泛型擦除带来的类型信息丢失问题。
  5. 与新数据结构兼容:支持如kotlinx.collections.immutable等新型集合库。

通过持续优化和功能扩展,Gson将继续为Android开发者提供高效、可靠的复杂数据结构处理方案。