【问题标题】:How do I implement TypeAdapterFactory in Gson?如何在 Gson 中实现 TypeAdapterFactory?
【发布时间】:2014-04-13 23:34:16
【问题描述】:

如何在 Gson 中实现 TypeAdapterFactory 类型?

create 的主要方法是泛型的。为什么?

注册方法registerTypeAdapterFactory() 不接收类型参数。那么,Gson 是如何知道工厂处理了哪些类的呢?

我应该为多个类实现一个工厂,还是可以为多个类实现一个工厂?

如果我为多个类实现一个工厂,那么在域外类型参数的情况下我应该返回什么?

【问题讨论】:

    标签: java json serialization gson deserialization


    【解决方案1】:

    当您注册一个常规类型适配器 (GsonBuilder.registerTypeAdapter) 时,它只会为该特定类生成一个类型适配器。例如:

    public abstract class Animal { abstract void speak(); }
    public class Dog extends Animal {
       private final String speech = "woof";
       public void speak() {
           System.out.println(speech);
       }
    }
    
    // in some gson related method
    gsonBuilder.registerTypeAdapter(Animal.class, myTypeAdapterObject);
    Gson g = gsonBuilder.create();
    Dog dog = new Dog();
    System.out.println(g.toJson(dog));
    

    如果你这样做了,那么Gson使用你的myTypeAdapterObject,它将使用Object 的默认类型适配器。

    那么,如何创建一个可以将任何Animal 子类转换为 Json 的类型适配器对象?创建一个TypeAdapterFactory!工厂可以使用泛型类型和TypeToken 类进行匹配。如果您的 TypeAdapterFactory 不知道如何处理该类型的对象,您应该返回 null。

    TypeAdapterFactory 可用于的另一件事是您不能以任何其他方式链接适配器。默认情况下,Gson 不会将您的 Gson 实例传递给 TypeAdapterreadwrite 方法。所以如果你有一个像这样的对象:

    public class MyOuterClass {
        private MyInnerClass inner;
    }
    

    如果不使用TypeAdapterFactory,就无法编写知道如何使用TypeAdapter<MyInnerClass>TypeAdapter<MyOuterClass>TypeAdapterFactory.create 方法确实传递了 Gson 实例,它允许您教您的 TypeAdapter<MyOuterClass> 如何序列化 MyInnerClass 字段。


    一般来说,这是开始编写TypeAdapterFactory 实现的一个很好的标准方法:

    public enum FooAdapterFactory implements TypeAdapterFactory {
        INSTANCE; // Josh Bloch's Enum singleton pattern
    
        @SuppressWarnings("unchecked")
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            if (!Foo.class.isAssignableFrom(type.getRawType())) return null;
    
            // Note: You have access to the `gson` object here; you can access other deserializers using gson.getAdapter and pass them into your constructor
            return (TypeAdapter<T>) new FooAdapter();
        }
    
        private static class FooAdapter extends TypeAdapter<Foo> {
            @Override
            public void write(JsonWriter out, Foo value) {
                // your code
            }
    
            @Override
            public Foo read(JsonReader in) throws IOException {
                // your code
            }
        }
    }
    

    【讨论】:

    • 那么,Gson 会为序列化期间遇到的数百个类调用我的适配器工厂吗?
    • 是的,但是Gson 保留了classAdapterFactory 的查找表,因此它只尝试您的课程一次。如果 create 返回 null 它永远不会再尝试该类。
    • @SuzanCioc 嗯,是的......我看源代码就知道了:-D
    • 如果FooAdapter 是唯一可以提供的适配器,那么为什么要使用TypeAdapterFactory?为什么不直接使用TypeAdapter
    • 因为TypeAdapter&lt;T&gt; 只能序列化一种特定类型,T。如果您想序列化一个接口和所有实现者,您需要在 Gson 查找表中为实现该接口的所有个请求的类创建一个引用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多