我如何在Gson中实现TypeAdapterFactory? [英] How do I implement TypeAdapterFactory in Gson?

查看:152
本文介绍了我如何在Gson中实现TypeAdapterFactory?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何实现类型 TypeAdapterFactory in Gson?



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



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



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



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

解决方案

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

//在某些与gson相关的方法中
gsonBuilder.registerTypeAdapter(Animal.class,myTypeAdapterObject);
Gson g = gsonBuilder.create();
狗狗=新狗();
System.out.println(g.toJson(dog));

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

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



另一个事物 TypeAdapterFactory 可用于您无法以任何其他方式链接适配器。默认情况下,Gson不会将 Gson 实例传递给 read write TypeAdapter 的方法。因此,如果你有一个对象:

  public class MyOuterClass {
private MyInnerClass inner;
}

无法编写 TypeAdapter< MyOuterClass> ; 知道如何在不使用 TypeAdapterFactory 的情况下使用 TypeAdapter< MyInnerClass> TypeAdapterFactory.create 方法可以传递 Gson 实例,它允许您教导 TypeAdapter< ; MyOuterClass> 如何序列化 MyInnerClass 字段。




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

  public enum FooAdapterFactory实现TypeAdapterFactory {
INSTANCE; // Josh Bloch的Enum单例模式

@SuppressWarnings(unchecked)
@Override
public< T> TypeAdapter< T> create(Gson gson,TypeToken< T> type){
if(!Foo.class.isAssignableFrom(type.getRawType()))return null;

//注意:你可以在这里访问`gson`对象;您可以使用gson.getAdapter来访问其他反序列化器并将它们传递到您的构造函数中
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)抛出IOException {
//您的代码
}
}
}


How do I implement type TypeAdapterFactory in Gson?

The main method of create is generic. Why?

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

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?

解决方案

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

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 Gson will not use your myTypeAdapterObject, it will use the default type adapter for Object.

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

The other thing TypeAdapterFactory can be used for is that you can't CHAIN adapters any other way. By default, Gson doesn't pass your Gson instance into the read or write methods of TypeAdapter. So if you have an object like:

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.create method DOES pass the Gson instance, which allows you to teach your TypeAdapter<MyOuterClass> how to serialize the MyInnerClass field.


Generally, here is a good standard way to begin to write an implementation of 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
        }
    }
}

这篇关于我如何在Gson中实现TypeAdapterFactory?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆