RuntimeTypeAdapterFactory.java

package com.example.renderer.util;

/**
 * RuntimeTypeAdapterFactory是Gson的类型适配器工厂,支持运行时多态类型的序列化/反序列化。
 * 解决Gson默认不支持多态类型的问题,通过类型字段(typeFieldName)来区分具体子类。
 *
 * <p>工作原理:
 * <ol>
 *   <li>序列化时添加类型标识字段</li>
 *   <li>反序列化时根据类型标识字段创建对应子类实例</li>
 * </ol>
 * </p>
 *
 * <p>典型用法:
 * <pre>{@code
 * RuntimeTypeAdapterFactory<Shape> adapterFactory = 
 *     RuntimeTypeAdapterFactory.of(Shape.class, "type")
 *         .registerSubtype(Circle.class, "circle")
 *         .registerSubtype(Rectangle.class, "rectangle");
 *
 * Gson gson = new GsonBuilder()
 *     .registerTypeAdapterFactory(adapterFactory)
 *     .create();
 * }</pre>
 * </p>
 *
 * <p>注意事项:
 * <ul>
 *   <li>类型字段名称(typeFieldName)必须在JSON中唯一</li>
 *   <li>所有子类必须提前注册</li>
 *   <li>子类需要有无参构造函数</li>
 * </ul>
 * </p>
 *
 * @see <a href="https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java">
 *     Gson官方类似实现</a>
 * @see Gson Google的JSON处理库
 * @author liying
 * @since 1.0
 * @version 1.0
 */

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.google.gson.internal.Streams;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 运行时类型适配器工厂类
 * @param <T> 基类型
 */
public class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
    private final Class<?> baseType;
    private final String typeFieldName;
    private final Map<String, Class<?>> labelToSubtype = new HashMap<>();
    private final Map<Class<?>, String> subtypeToLabel = new HashMap<>();

    private RuntimeTypeAdapterFactory(Class<?> baseType, String typeFieldName) {
        this.baseType = baseType;
        this.typeFieldName = typeFieldName;
    }

    /**
     * 创建运行时类型适配器工厂
     * 
     * @param <T> 基类型
     * @param baseType 基类
     * @param typeFieldName JSON中的类型字段名
     * @return 适配器工厂实例
     */
    public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
        return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName);
    }

    /**
     * 注册子类型
     * 
     * @param type 子类型类对象
     * @param label 类型标签
     * @return 适配器工厂实例(用于链式调用)
     */
    public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type, String label) {
        labelToSubtype.put(label, type);
        subtypeToLabel.put(type, label);
        return this;
    }

    @Override
    public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
        if (!baseType.isAssignableFrom(type.getRawType())) {
            return null;
        }

        final Map<String, TypeAdapter<?>> labelToDelegate = new HashMap<>();
        final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate = new HashMap<>();

        for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
            TypeAdapter<?> delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
            labelToDelegate.put(entry.getKey(), delegate);
            subtypeToDelegate.put(entry.getValue(), delegate);
        }

        return new TypeAdapter<R>() {
            @SuppressWarnings("unchecked")
            @Override
            public void write(JsonWriter out, R value) throws IOException {
                Class<?> srcType = value.getClass();
                String label = subtypeToLabel.get(srcType);
                if (label == null) {
                    throw new JsonParseException("Cannot serialize " + srcType.getName());
                }
                TypeAdapter<R> delegate = (TypeAdapter<R>) subtypeToDelegate.get(srcType);
                JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
                jsonObject.addProperty(typeFieldName, label);
                Streams.write(jsonObject, out);
            }

            @SuppressWarnings("unchecked")
            @Override
            public R read(JsonReader in) throws IOException {
                JsonElement jsonElement = Streams.parse(in);
                JsonObject jsonObject = jsonElement.getAsJsonObject();
                JsonElement labelJsonElement = jsonObject.remove(typeFieldName);
                if (labelJsonElement == null) {
                    throw new JsonParseException("Cannot deserialize missing type field: " + typeFieldName);
                }
                String label = labelJsonElement.getAsString();
                TypeAdapter<?> delegate = labelToDelegate.get(label);
                if (delegate == null) {
                    throw new JsonParseException("Unknown label: " + label);
                }
                return (R) delegate.fromJsonTree(jsonObject);
            }
        };
    }
}