Java 如何在 Gson 中实现 TypeAdapterFactory?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22307382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:51:06  来源:igfitidea点击:

How do I implement TypeAdapterFactory in Gson?

javajsonserializationgsondeserialization

提问by Suzan Cioc

How do I implement type TypeAdapterFactoryin Gson?

如何在 Gson 中实现TypeAdapterFactory类型?

The main method of create is generic. Why?

create 的主要方法是通用的。为什么?

The registration method registerTypeAdapterFactory()does not receive type a type argument. So, how does Gsonknow which classes are processed by the factory?

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

Should I implement one factory for multiple classes, or can I implement one for many classes?

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

If I implement one factory for multiple classes, then what should I return in case of out-of-domain type argument?

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

回答by durron597

When you register a regular type adapter (GsonBuilder.registerTypeAdapter), it only generates a type adapter for THAT specific class. For example:

当您注册常规类型适配器 ( 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));

If you did this, then Gsonwill notuse your myTypeAdapterObject, it will use the default type adapter for Object.

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

So, how can you make a type adapter object that can convert ANY Animalsubclass to Json? Create a TypeAdapterFactory! The factory can match using the generic type and the TypeTokenclass. You should return null if your TypeAdapterFactorydoesn't know how to handle an object of that type.

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

The other thing TypeAdapterFactorycan be used for is that you can't CHAIN adapters any other way. By default, Gson doesn't pass your Gsoninstance into the reador writemethods of TypeAdapter. So if you have an object like:

另一件事TypeAdapterFactory可用于您不能以任何其他方式连接适配器。默认情况下,Gson 不会将您的Gson实例传递到 的readwrite方法中TypeAdapter。因此,如果您有一个对象,例如:

public class MyOuterClass {
    private MyInnerClass inner;
}

There is no way to write your TypeAdapter<MyOuterClass>that knows how to use your TypeAdapter<MyInnerClass>without using the TypeAdapterFactory. The TypeAdapterFactory.createmethod DOES pass the Gsoninstance, which allows you to teach your TypeAdapter<MyOuterClass>how to serialize the MyInnerClassfield.

有没有办法写你TypeAdapter<MyOuterClass>知道如何使用您TypeAdapter<MyInnerClass>不使用TypeAdapterFactory。该TypeAdapterFactory.create方法确实传递了Gson实例,它允许您教您TypeAdapter<MyOuterClass>如何序列化MyInnerClass字段。



Generally, here is a good standard way to begin to write an implementation of a TypeAdapterFactory:

通常,这是开始编写 a 实现的一个很好的标准方法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
        }
    }
}