Android Gson TypeAdapter接口定义与核心方法(10)

65 阅读16分钟

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

一、TypeAdapter接口概述

1.1 TypeAdapter在Gson中的核心地位

在Android开发中,Gson作为主流的JSON处理框架,其核心功能之一是实现Java对象与JSON数据之间的相互转换。而TypeAdapter接口则是这一转换过程的核心抽象,它定义了序列化和反序列化的基本操作,为开发者提供了高度定制化的数据转换能力。

TypeAdapter是Gson 2.0版本引入的一个抽象类,相比早期使用的JsonSerializer和JsonDeserializer接口,TypeAdapter提供了更高效、更统一的API,避免了中间Tree模型的使用,从而提高了性能。

1.2 TypeAdapter接口的定义

TypeAdapter接口的定义如下:

public abstract class TypeAdapter<T> {
    // 将Java对象序列化为JSON
    public abstract void write(JsonWriter out, T value) throws IOException;
    
    // 将JSON反序列化为Java对象
    public abstract T read(JsonReader in) throws IOException;
    
    // 以下是一些默认实现的便捷方法
    
    // 将Java对象转换为JSON字符串
    public final String toJson(T value) throws JsonIOException {
        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = newJsonWriter(stringWriter);
        try {
            write(jsonWriter, value);
            jsonWriter.close();
            return stringWriter.toString();
        } catch (IOException e) {
            throw new JsonIOException(e);
        }
    }
    
    // 从JSON字符串解析为Java对象
    public final T fromJson(String json) throws JsonSyntaxException {
        StringReader stringReader = new StringReader(json);
        return fromJson(stringReader);
    }
    
    // 从Reader解析为Java对象
    public final T fromJson(Reader reader) throws JsonIOException, JsonSyntaxException {
        JsonReader jsonReader = newJsonReader(reader);
        return read(jsonReader);
    }
    
    // 创建JsonWriter实例
    protected JsonWriter newJsonWriter(Writer writer) {
        return new JsonWriter(writer);
    }
    
    // 创建JsonReader实例
    protected JsonReader newJsonReader(Reader reader) {
        return new JsonReader(reader);
    }
}

1.3 TypeAdapter与其他序列化接口的关系

在Gson中,除了TypeAdapter接口外,还有JsonSerializer和JsonDeserializer接口用于处理序列化和反序列化。它们之间的关系如下:

  • JsonSerializer和JsonDeserializer:这是Gson早期提供的接口,分别用于处理序列化和反序列化。它们的实现需要处理JsonElement中间对象,性能相对较低。
  • TypeAdapter:是Gson 2.0引入的更高效的接口,直接操作JsonWriter和JsonReader,避免了中间对象的创建,提高了性能。
  • TypeAdapterFactory:用于创建TypeAdapter的工厂接口,可以根据类型动态提供适配器。

Gson内部会将JsonSerializer和JsonDeserializer封装为TypeAdapter,以统一处理流程:

// TreeTypeAdapter类 - 用于封装JsonSerializer和JsonDeserializer
public final class TreeTypeAdapter<T> extends TypeAdapter<T> {
    private final JsonSerializer<T> serializer;
    private final JsonDeserializer<T> deserializer;
    private final Gson gson;
    private final TypeToken<T> typeToken;
    private final TypeAdapterFactory skipPast;
    private TypeAdapter<T> delegate; // 延迟初始化的委托适配器
    
    // 构造函数
    public TreeTypeAdapter(JsonSerializer<T> serializer,
                           JsonDeserializer<T> deserializer,
                           Gson gson,
                           TypeToken<T> typeToken,
                           TypeAdapterFactory skipPast) {
        this.serializer = serializer;
        this.deserializer = deserializer;
        this.gson = gson;
        this.typeToken = typeToken;
        this.skipPast = skipPast;
    }
    
    // 实现TypeAdapter的write方法
    @Override public void write(JsonWriter out, T value) throws IOException {
        if (serializer == null) {
            // 如果没有提供序列化器,使用委托适配器
            delegate().write(out, value);
            return;
        }
        
        if (value == null) {
            out.nullValue();
            return;
        }
        
        // 使用JsonSerializer将对象转换为JsonElement
        JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext());
        // 将JsonElement写入JsonWriter
        Streams.write(tree, out);
    }
    
    // 实现TypeAdapter的read方法
    @Override public T read(JsonReader in) throws IOException {
        if (deserializer == null) {
            // 如果没有提供反序列化器,使用委托适配器
            return delegate().read(in);
        }
        
        // 从JsonReader读取JsonElement
        JsonElement jsonTree = Streams.parse(in);
        if (jsonTree.isJsonNull()) {
            return null;
        }
        
        // 使用JsonDeserializer将JsonElement转换为对象
        return deserializer.deserialize(jsonTree, typeToken.getType(), gson.deserializationContext());
    }
    
    // 获取委托适配器
    private TypeAdapter<T> delegate() {
        TypeAdapter<T> d = delegate;
        return d != null
                ? d
                : (delegate = gson.getDelegateAdapter(skipPast, typeToken));
    }
}

二、核心方法write的原理

2.1 write方法的定义与作用

write方法是TypeAdapter接口中定义的用于将Java对象序列化为JSON的核心方法。其定义如下:

public abstract void write(JsonWriter out, T value) throws IOException;

该方法接收两个参数:

  • JsonWriter out:用于写入JSON数据的写入器
  • T value:待序列化的Java对象

2.2 write方法的基本实现流程

在自定义TypeAdapter时,实现write方法通常需要遵循以下步骤:

  1. 处理null值:首先检查对象是否为null,如果为null,调用out.nullValue()方法写入null值。
  2. 开始写入JSON结构:根据对象类型,调用out.beginObject()开始写入对象,或调用out.beginArray()开始写入数组。
  3. 写入对象属性或数组元素:遍历对象的属性或数组的元素,调用相应的out.name()out.value()方法写入属性名和值。
  4. 结束JSON结构:调用out.endObject()out.endArray()结束对象或数组的写入。

2.3 源码级实现分析

下面通过一个具体的例子来分析write方法的实现原理。假设我们有一个简单的User类:

class User {
    private String name;
    private int age;
    private boolean isAdmin;
    
    // 构造方法和getter/setter省略
}

我们可以为其创建一个自定义的TypeAdapter:

class UserTypeAdapter extends TypeAdapter<User> {
    @Override
    public void write(JsonWriter out, User value) throws IOException {
        // 处理null值
        if (value == null) {
            out.nullValue();
            return;
        }
        
        // 开始写入JSON对象
        out.beginObject();
        
        // 写入name属性
        out.name("name");
        out.value(value.getName());
        
        // 写入age属性
        out.name("age");
        out.value(value.getAge());
        
        // 写入isAdmin属性
        out.name("isAdmin");
        out.value(value.isAdmin());
        
        // 结束JSON对象
        out.endObject();
    }
    
    // read方法实现省略
}

Gson内部在序列化时会调用这个write方法。让我们深入分析JsonWriter的关键方法实现:

public final class JsonWriter {
    // 写入null值
    public JsonWriter nullValue() throws IOException {
        if (closed) throw new IOException("JsonWriter is closed");
        beforeValue();
        out.write("null");
        return this;
    }
    
    // 开始写入JSON对象
    public JsonWriter beginObject() throws IOException {
        if (closed) throw new IOException("JsonWriter is closed");
        writeDeferredName();
        return open(JsonScope.EMPTY_OBJECT, "{");
    }
    
    // 写入属性名
    public JsonWriter name(String name) throws IOException {
        if (name == null) throw new NullPointerException("name == null");
        if (closed) throw new IOException("JsonWriter is closed");
        writeDeferredName();
        return string(name);
    }
    
    // 写入字符串值
    public JsonWriter value(String value) throws IOException {
        if (value == null) {
            return nullValue();
        }
        beforeValue();
        string(value);
        return this;
    }
    
    // 写入整数值
    public JsonWriter value(long value) throws IOException {
        if (closed) throw new IOException("JsonWriter is closed");
        beforeValue();
        out.write(Long.toString(value));
        return this;
    }
    
    // 写入布尔值
    public JsonWriter value(boolean value) throws IOException {
        if (closed) throw new IOException("JsonWriter is closed");
        beforeValue();
        out.write(value ? "true" : "false");
        return this;
    }
    
    // 结束写入JSON对象
    public JsonWriter endObject() throws IOException {
        return close(JsonScope.EMPTY_OBJECT, JsonScope.NONEMPTY_OBJECT, "}");
    }
    
    // 内部方法:写入字符串
    private void string(String value) throws IOException {
        out.write('"');
        // 转义特殊字符
        String escaped = stringPool.get(value);
        if (escaped == null) {
            escaped = JsonEscaper.escape(value);
            stringPool.put(value, escaped);
        }
        out.write(escaped);
        out.write('"');
    }
}

2.4 处理嵌套对象和集合

当对象包含嵌套对象或集合时,write方法需要递归处理这些嵌套结构。例如,假设User类包含一个Address对象和一个爱好列表:

class User {
    private String name;
    private Address address;
    private List<String> hobbies;
    
    // 构造方法和getter/setter省略
}

class Address {
    private String street;
    private String city;
    
    // 构造方法和getter/setter省略
}

对应的TypeAdapter实现如下:

class UserTypeAdapter extends TypeAdapter<User> {
    private final TypeAdapter<Address> addressAdapter;
    private final TypeAdapter<String> stringAdapter;
    
    public UserTypeAdapter(Gson gson) {
        // 获取Address和String的适配器
        addressAdapter = gson.getAdapter(Address.class);
        stringAdapter = gson.getAdapter(String.class);
    }
    
    @Override
    public void write(JsonWriter out, User value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        
        out.beginObject();
        
        // 写入name
        out.name("name");
        stringAdapter.write(out, value.getName());
        
        // 写入address
        out.name("address");
        addressAdapter.write(out, value.getAddress());
        
        // 写入hobbies
        out.name("hobbies");
        out.beginArray();
        for (String hobby : value.getHobbies()) {
            stringAdapter.write(out, hobby);
        }
        out.endArray();
        
        out.endObject();
    }
    
    // read方法省略
}

在这个例子中,我们通过Gson获取了Address和String的适配器,并在写入嵌套对象和集合时调用它们的write方法,实现了递归处理。

三、核心方法read的原理

3.1 read方法的定义与作用

read方法是TypeAdapter接口中定义的用于将JSON数据反序列化为Java对象的核心方法。其定义如下:

public abstract T read(JsonReader in) throws IOException;

该方法接收一个参数:

  • JsonReader in:用于读取JSON数据的读取器

方法返回反序列化后的Java对象。

3.2 read方法的基本实现流程

在自定义TypeAdapter时,实现read方法通常需要遵循以下步骤:

  1. 检查JSON类型:首先检查当前JSON元素的类型(如对象、数组、字符串等)。
  2. 根据类型解析数据:根据JSON元素的类型,调用相应的读取方法(如in.beginObject()in.nextString()等)。
  3. 构建Java对象:将读取的数据转换为Java对象的属性值,并构建最终的Java对象。
  4. 返回结果:返回构建好的Java对象。

3.3 源码级实现分析

继续使用上面的User类示例,实现其read方法:

class UserTypeAdapter extends TypeAdapter<User> {
    @Override
    public User read(JsonReader in) throws IOException {
        // 处理null值
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        
        // 创建User对象
        User user = new User();
        
        // 开始解析JSON对象
        in.beginObject();
        
        while (in.hasNext()) {
            // 读取属性名
            String name = in.nextName();
            
            // 根据属性名处理不同的属性
            switch (name) {
                case "name":
                    user.setName(in.nextString());
                    break;
                case "age":
                    user.setAge(in.nextInt());
                    break;
                case "isAdmin":
                    user.setAdmin(in.nextBoolean());
                    break;
                default:
                    // 跳过未知属性
                    in.skipValue();
                    break;
            }
        }
        
        // 结束解析JSON对象
        in.endObject();
        
        return user;
    }
    
    // write方法实现省略
}

让我们深入分析JsonReader的关键方法实现:

public final class JsonReader {
    // 查看下一个JSON元素的类型
    public JsonToken peek() throws IOException {
        if (closed) throw new IllegalStateException("JsonReader is closed");
        int p = peeked;
        if (p == PEEKED_NONE) {
            p = doPeek();
            peeked = p;
        }
        return getToken(p);
    }
    
    // 读取null值
    public void nextNull() throws IOException {
        if (peek() != JsonToken.NULL) {
            throw new IllegalStateException("Expected null but was " + peek() + locationString());
        }
        consumeValue();
        pathIndices[stackSize - 1]++;
    }
    
    // 开始解析JSON对象
    public void beginObject() throws IOException {
        if (peek() != JsonToken.BEGIN_OBJECT) {
            throw new IllegalStateException("Expected BEGIN_OBJECT but was " + peek() + locationString());
        }
        int p = stack[stackSize - 1];
        if (p == SCOPE_EMPTY_ARRAY) {
            stack[stackSize - 1] = SCOPE_NONEMPTY_ARRAY;
        } else if (p == SCOPE_EMPTY_OBJECT || p == SCOPE_DANGLING_NAME) {
            stack[stackSize - 1] = SCOPE_NONEMPTY_OBJECT;
        } else {
            throw new IllegalStateException("Nesting problem.");
        }
        stack[stackSize++] = SCOPE_EMPTY_OBJECT;
        pathNames[stackSize - 1] = null;
        pathIndices[stackSize - 1] = 0;
        consumeValue();
    }
    
    // 读取下一个属性名
    public String nextName() throws IOException {
        if (peek() != JsonToken.NAME) {
            throw new IllegalStateException("Expected a name but was " + peek() + locationString());
        }
        String result = readString();
        stack[stackSize - 1] = SCOPE_DANGLING_NAME;
        pathNames[stackSize - 1] = result;
        pathIndices[stackSize - 1] = 0;
        return result;
    }
    
    // 读取下一个字符串值
    public String nextString() throws IOException {
        JsonToken token = peek();
        if (token == JsonToken.STRING || token == JsonToken.NUMBER) {
            return readString();
        }
        if (token == JsonToken.NULL) {
            nextNull();
            return null;
        }
        if (token == JsonToken.BOOLEAN) {
            return Boolean.toString(nextBoolean());
        }
        throw new IllegalStateException("Expected a string but was " + token + locationString());
    }
    
    // 读取下一个整数值
    public int nextInt() throws IOException {
        JsonToken token = peek();
        if (token != JsonToken.NUMBER && token != JsonToken.STRING) {
            throw new IllegalStateException("Expected NUMBER but was " + token + locationString());
        }
        String value = readString();
        try {
            int result = Integer.parseInt(value);
            if (value.equals(Integer.toString(result))) {
                pathIndices[stackSize - 1]++;
                return result;
            }
        } catch (NumberFormatException e) {
            // 处理数字格式异常
        }
        throw new NumberFormatException("Expected an int but was " + value + locationString());
    }
    
    // 结束解析JSON对象
    public void endObject() throws IOException {
        if (peek() != JsonToken.END_OBJECT) {
            throw new IllegalStateException("Expected END_OBJECT but was " + peek() + locationString());
        }
        stackSize--;
        if (stackSize == 0) {
            closed = true;
        }
        pathIndices[stackSize - 1]++;
        consumeValue();
    }
}

3.4 处理嵌套对象和集合

当JSON数据包含嵌套对象或集合时,read方法需要递归处理这些嵌套结构。继续使用上面的User类示例,实现其完整的read方法:

class UserTypeAdapter extends TypeAdapter<User> {
    private final TypeAdapter<Address> addressAdapter;
    private final TypeAdapter<String> stringAdapter;
    
    public UserTypeAdapter(Gson gson) {
        addressAdapter = gson.getAdapter(Address.class);
        stringAdapter = gson.getAdapter(String.class);
    }
    
    @Override
    public User read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        
        User user = new User();
        
        in.beginObject();
        
        while (in.hasNext()) {
            String name = in.nextName();
            
            switch (name) {
                case "name":
                    user.setName(in.nextString());
                    break;
                case "address":
                    // 递归解析Address对象
                    user.setAddress(addressAdapter.read(in));
                    break;
                case "hobbies":
                    // 解析hobbies集合
                    List<String> hobbies = new ArrayList<>();
                    in.beginArray();
                    while (in.hasNext()) {
                        hobbies.add(stringAdapter.read(in));
                    }
                    in.endArray();
                    user.setHobbies(hobbies);
                    break;
                default:
                    in.skipValue();
                    break;
            }
        }
        
        in.endObject();
        
        return user;
    }
    
    // write方法省略
}

在这个例子中,我们通过Gson获取了Address和String的适配器,并在解析嵌套对象和集合时调用它们的read方法,实现了递归处理。

四、TypeAdapter的注册与发现机制

4.1 通过GsonBuilder注册TypeAdapter

在使用Gson时,需要通过GsonBuilder注册自定义的TypeAdapter。注册方法如下:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(User.class, new UserTypeAdapter())
    .create();

GsonBuilder的registerTypeAdapter方法实现如下:

public final class GsonBuilder {
    private final List<TypeAdapterFactory> factories = new ArrayList<>();
    
    // 注册TypeAdapter的方法
    public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
        if (type == null) {
            throw new NullPointerException("type == null");
        }
        if (typeAdapter == null) {
            throw new NullPointerException("typeAdapter == null");
        }
        
        // 将TypeAdapter包装为TypeAdapterFactory
        factories.add(TypeAdapters.newFactory(TypeToken.get(type), typeAdapter));
        return this;
    }
    
    // 创建Gson实例
    public Gson create() {
        List<TypeAdapterFactory> factories = new ArrayList<>();
        
        // 添加用户注册的工厂
        factories.addAll(this.factories);
        
        // 添加Gson内置的工厂
        factories.addAll(Gson.DEFAULT_FACTORIES);
        
        return new Gson(factories);
    }
}

4.2 TypeAdapter的发现过程

当Gson需要序列化或反序列化某个类型时,会通过TypeAdapterFactory查找对应的TypeAdapter。这个过程在Gson类的getAdapter方法中实现:

public final class Gson {
    private final List<TypeAdapterFactory> factories;
    
    // 获取TypeAdapter的方法
    public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
        // 从缓存中查找TypeAdapter
        TypeAdapter<?> cached = typeTokenCache.get(type);
        if (cached != null) {
            return (TypeAdapter<T>) cached;
        }
        
        // 为防止循环引用,先将一个占位符放入缓存
        Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
        boolean requiresThreadLocalCleanup = false;
        if (threadCalls == null) {
            threadCalls = new HashMap<>();
            calls.set(threadCalls);
            requiresThreadLocalCleanup = true;
        }
        
        // 检查是否存在循环引用
        FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
        if (ongoingCall != null) {
            return ongoingCall;
        }
        
        try {
            // 创建一个占位符
            FutureTypeAdapter<T> call = new FutureTypeAdapter<>();
            threadCalls.put(type, call);
            
            // 遍历工厂列表,查找能够处理该类型的工厂
            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 cannot handle " + type);
        } finally {
            threadCalls.remove(type);
            if (requiresThreadLocalCleanup) {
                calls.remove();
            }
        }
    }
}

4.3 TypeAdapterFactory的实现

TypeAdapterFactory是一个接口,用于创建TypeAdapter实例:

public interface TypeAdapterFactory {
    // 为指定类型创建TypeAdapter
    <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}

Gson提供了多种内置的TypeAdapterFactory,如:

  • ReflectiveTypeAdapterFactory:基于反射处理普通Java对象
  • CollectionTypeAdapterFactory:处理集合类型
  • MapTypeAdapterFactory:处理Map类型
  • ArrayTypeAdapter:处理数组类型

自定义TypeAdapterFactory的实现示例:

class CustomTypeAdapterFactory implements TypeAdapterFactory {
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // 判断是否为我们感兴趣的类型
        if (type.getRawType() == User.class) {
            // 返回自定义的TypeAdapter
            return (TypeAdapter<T>) new UserTypeAdapter(gson);
        }
        
        // 不是我们感兴趣的类型,返回null
        return null;
    }
}

五、TypeAdapter的性能优化

5.1 避免中间Tree模型

TypeAdapter相比JsonSerializer和JsonDeserializer的一个重要优势是避免了中间Tree模型的使用。在使用JsonSerializer和JsonDeserializer时,Gson会先将JSON数据解析为JsonElement树结构,然后再进行处理,这会增加内存开销和处理时间。而TypeAdapter直接操作JsonWriter和JsonReader,避免了中间对象的创建,提高了性能。

5.2 缓存反射结果

在处理复杂对象时,反射操作可能成为性能瓶颈。可以通过缓存反射结果来优化性能。例如:

class UserTypeAdapter extends TypeAdapter<User> {
    private final Constructor<User> constructor;
    private final Field nameField;
    private final Field ageField;
    private final Field isAdminField;
    
    public UserTypeAdapter() throws NoSuchMethodException, NoSuchFieldException {
        // 获取构造函数并设置可访问
        constructor = User.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        
        // 获取字段并设置可访问
        nameField = User.class.getDeclaredField("name");
        nameField.setAccessible(true);
        
        ageField = User.class.getDeclaredField("age");
        ageField.setAccessible(true);
        
        isAdminField = User.class.getDeclaredField("isAdmin");
        isAdminField.setAccessible(true);
    }
    
    @Override
    public User read(JsonReader in) throws IOException {
        try {
            // 使用缓存的构造函数创建实例
            User user = constructor.newInstance();
            
            in.beginObject();
            
            while (in.hasNext()) {
                String name = in.nextName();
                
                switch (name) {
                    case "name":
                        // 使用缓存的字段设置值
                        nameField.set(user, in.nextString());
                        break;
                    case "age":
                        ageField.set(user, in.nextInt());
                        break;
                    case "isAdmin":
                        isAdminField.set(user, in.nextBoolean());
                        break;
                    default:
                        in.skipValue();
                        break;
                }
            }
            
            in.endObject();
            
            return user;
        } catch (Exception e) {
            throw new JsonSyntaxException(e);
        }
    }
    
    // write方法省略
}

5.3 批量处理数据

在处理大量数据时,批量处理可以减少对象创建和方法调用的开销。例如,在处理集合时,可以批量读取或写入元素:

class UserListTypeAdapter extends TypeAdapter<List<User>> {
    private final TypeAdapter<User> userAdapter;
    
    public UserListTypeAdapter(Gson gson) {
        userAdapter = gson.getAdapter(User.class);
    }
    
    @Override
    public void write(JsonWriter out, List<User> value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        
        out.beginArray();
        
        // 批量处理元素
        for (User user : value) {
            userAdapter.write(out, user);
        }
        
        out.endArray();
    }
    
    @Override
    public List<User> read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        
        List<User> list = new ArrayList<>();
        
        in.beginArray();
        
        // 批量处理元素
        while (in.hasNext()) {
            list.add(userAdapter.read(in));
        }
        
        in.endArray();
        
        return list;
    }
}

六、TypeAdapter的高级应用

6.1 处理多态类型

当需要处理多态类型时,可以在TypeAdapter中根据对象的实际类型进行不同的处理。例如,假设我们有一个Shape接口和多个实现类:

interface Shape {
    double getArea();
}

class Circle implements Shape {
    private double radius;
    
    // 构造方法和getter/setter省略
}

class Rectangle implements Shape {
    private double width;
    private double height;
    
    // 构造方法和getter/setter省略
}

我们可以创建一个处理Shape接口的TypeAdapter:

class ShapeTypeAdapter extends TypeAdapter<Shape> {
    private static final String TYPE_FIELD = "type";
    private static final String CIRCLE = "circle";
    private static final String RECTANGLE = "rectangle";
    
    @Override
    public void write(JsonWriter out, Shape value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        
        out.beginObject();
        
        // 写入类型标识
        if (value instanceof Circle) {
            out.name(TYPE_FIELD).value(CIRCLE);
            Circle circle = (Circle) value;
            out.name("radius").value(circle.getRadius());
        } else if (value instanceof Rectangle) {
            out.name(TYPE_FIELD).value(RECTANGLE);
            Rectangle rectangle = (Rectangle) value;
            out.name("width").value(rectangle.getWidth());
            out.name("height").value(rectangle.getHeight());
        }
        
        out.endObject();
    }
    
    @Override
    public Shape read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        
        Shape shape = null;
        
        in.beginObject();
        
        String type = null;
        double radius = 0;
        double width = 0;
        double height = 0;
        
        while (in.hasNext()) {
            String name = in.nextName();
            
            switch (name) {
                case TYPE_FIELD:
                    type = in.nextString();
                    break;
                case "radius":
                    radius = in.nextDouble();
                    break;
                case "width":
                    width = in.nextDouble();
                    break;
                case "height":
                    height = in.nextDouble();
                    break;
                default:
                    in.skipValue();
                    break;
            }
        }
        
        in.endObject();
        
        // 根据类型创建对象
        if (CIRCLE.equals(type)) {
            shape = new Circle(radius);
        } else if (RECTANGLE.equals(type)) {
            shape = new Rectangle(width, height);
        }
        
        return shape;
    }
}

6.2 数据加密与解密

TypeAdapter还可以用于数据的加密和解密。例如,对敏感数据进行加密:

class EncryptedStringTypeAdapter extends TypeAdapter<String> {
    private final Cipher encryptCipher;
    private final Cipher decryptCipher;
    
    public EncryptedStringTypeAdapter() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        // 初始化加密和解密的Cipher
        SecretKeySpec secretKey = new SecretKeySpec("MySecretKey12345".getBytes(), "AES");
        encryptCipher = Cipher.getInstance("AES");
        encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
        
        decryptCipher = Cipher.getInstance("AES");
        decryptCipher.init(Cipher.DECRYPT_MODE, secretKey);
    }
    
    @Override
    public void write(JsonWriter out, String value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        
        try {
            // 加密字符串
            byte[] encryptedBytes = encryptCipher.doFinal(value.getBytes());
            // 将加密后的字节数组转换为Base64编码
            String encryptedString = Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
            out.value(encryptedString);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new IOException("Encryption error", e);
        }
    }
    
    @Override
    public String read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        
        String encryptedString = in.nextString();
        
        try {
            // 将Base64编码的字符串转换为字节数组
            byte[] encryptedBytes = Base64.decode(encryptedString, Base64.DEFAULT);
            // 解密字节数组
            byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes);
            return new String(decryptedBytes);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            throw new IOException("Decryption error", e);
        }
    }
}

6.3 自定义日期格式

TypeAdapter可以用于实现自定义的日期格式。例如:

class CustomDateTypeAdapter extends TypeAdapter<Date> {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    
    @Override
    public void write(JsonWriter out, Date value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        
        // 格式化日期
        String formattedDate = dateFormat.format(value);
        out.value(formattedDate);
    }
    
    @Override
    public Date read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        
        String dateString = in.nextString();
        
        try {
            // 解析日期
            return dateFormat.parse(dateString);
        } catch (ParseException e) {
            throw new JsonSyntaxException("Invalid date format: " + dateString, e);
        }
    }
}

七、TypeAdapter与JsonReader/JsonWriter的协作

7.1 JsonReader的工作原理

JsonReader是Gson中用于读取JSON数据的核心类。它提供了一系列方法用于解析JSON的各种结构,如对象、数组、字符串、数字等。

JsonReader的核心机制是基于状态机的。它维护一个内部状态,指示当前正在解析的JSON结构的类型和位置。每次调用读取方法时,它会根据当前状态检查输入是否符合预期,并更新状态。

例如,当调用beginObject()方法时,JsonReader会检查当前字符是否为{,如果是,则进入对象解析状态;否则抛出异常。

7.2 JsonWriter的工作原理

JsonWriter是Gson中用于写入JSON数据的核心类。它提供了一系列方法用于生成JSON的各种结构,如对象、数组、字符串、数字等。

JsonWriter同样基于状态机工作。它维护一个内部状态,记录当前正在生成的JSON结构的类型和位置。每次调用写入方法时,它会根据当前状态生成适当的JSON语法,并更新状态。

例如,当调用beginObject()方法时,JsonWriter会写入{字符,并进入对象写入状态;当调用name()方法时,它会写入属性名,并更新状态为等待属性值。

7.3 TypeAdapter与JsonReader/JsonWriter的交互

TypeAdapter通过JsonReader和JsonWriter实现与JSON数据的交互。在反序列化时,TypeAdapter调用JsonReader的方法读取JSON数据;在序列化时,TypeAdapter调用JsonWriter的方法写入JSON数据。

这种交互模式使得TypeAdapter可以完全控制数据的转换过程,实现高度定制化的序列化和反序列化逻辑。

例如,在前面的UserTypeAdapter示例中,read方法调用JsonReader的beginObject()nextName()nextString()等方法读取JSON数据;write方法调用JsonWriter的beginObject()name()value()等方法写入JSON数据。

八、总结与展望

8.1 TypeAdapter的优势

TypeAdapter作为Gson的核心接口,具有以下优势:

  1. 高性能:直接操作JsonReader和JsonWriter,避免中间Tree模型,提高了序列化和反序列化的效率。
  2. 灵活性:可以完全控制数据的转换过程,实现高度定制化的序列化和反序列化逻辑。
  3. 类型安全:基于泛型的设计,提供了更好的类型安全性。
  4. 扩展性:可以通过TypeAdapterFactory动态提供适配器,支持复杂的类型处理。

8.2 TypeAdapter的未来发展

随着Android和Java技术的发展,TypeAdapter可能会在以下方向发展:

  1. Kotlin协程支持:更好地支持Kotlin协程,实现异步序列化和反序列化。
  2. 编译时处理:引入编译时注解处理,在编译期生成TypeAdapter代码,进一步提高性能。
  3. 多平台支持:在Kotlin Multiplatform项目中提供更好的支持,实现跨平台的数据转换。
  4. 简化API:提供更简洁的API,降低开发者使用门槛。
  5. 与其他框架集成:更紧密地集成其他Android和Java框架,如Room、Retrofit等。

通过不断优化和扩展,TypeAdapter将继续作为Gson的核心组件,为开发者提供高效、灵活的数据转换解决方案。