GsonBuilder - 从接口获取对象

GsonBuilder - Get Object from Interface

我有一个 GsonFactory 声明如下:

public class GsonFactory {
    public Gson create() {
        return new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(MyInterface.class, new MyInstanceCreator())
                .create();
    }

    private static final GsonFactory instance = new GsonFactory();

    private GsonFactory() {
    }

    public static Gson getInstance(){
        return instance.create();
    }
}

我也有 InstanceCreator class:

public class MyInstanceCreator implements InstanceCreator<MyInterface> {
    @Override
    public StrategySymbol createInstance(Type type) {
        return new MyInterfaceImpl();
    }
}

class MyClass {
  private List<MyInterface> myList;

  public List<MyInterface> getMyList() { return myList; }

  public void setMyList(List<MyInterface> myList) { this.myList = myList; }
}

interface MyInterface {
  Long getValue1();
  void setValue1(Long value1);
}

class MyInterfaceImpl implements MyInterface {
  private Long value1;

  @Override
  public Long getValue1() {
     return value1;
  }

  @Override
  public void setValue1(Long value1) {
     this.value1 = value1
  }
}

此代码似乎实现良好,但如果我尝试用 value1:

解析 JSON
MyClass obj = GsonFactory.getInstance().fromJson("{'myList': [{'value1':8}]}", MyClass.class);

返回对象时带有 MyInterfaceImpl 的实例,但字段 value1 始终为空。如我所见,Gson 似乎在 interface (none) 中查找字段,而不是在实现 interfaceclass 中查找字段。

有人知道怎么解决吗?

InstanceCreator 只能创建未定义 no-args 构造函数的 class 的实例。它不处理反序列化。 Gson 仍然无法确定对象的具体数据类型。

解决。接口的自定义解串器
您需要为您的接口定义一个自定义反序列化器并在工厂中注册这个新类型的适配器。

public class MyInterfaceDeserializer implements JsonDeserializer<MyInterface> {
    @Override
    public MyInterface deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        return jsonDeserializationContext.deserialize(jsonElement, MyInterfaceImpl.class);
    }
}

public class GsonFactory {
    public Gson create() {
        return new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(MyInterface.class, new MyInterfaceDeserializer())
                .create();
    }
}

或通用解串器

public class InterfaceDeserializer<T, E> implements JsonDeserializer<T> {
    private final Class<E> implementationClass;

    public InterfaceDeserializer(Class<E> implementationClass) {
        this.implementationClass = implementationClass;
    }

    @Override
    public T deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        return jsonDeserializationContext.deserialize(jsonElement, implementationClass);
    }
}

public class GsonFactory {
    public Gson create() {     
        return new GsonBuilder()
                .setPrettyPrinting()                
               .registerTypeAdapter(MyInterface.class, new InterfaceDeserializer<MyInterface, MyInterfaceImpl>(MyInterfaceImpl.class))
                .create();
}

public class MyInterfaceDeserializer implements JsonDeserializer<MyInterface> {
    @Override
    public MyInterface deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
        MyInterface myInterface = new MyInterfaceImpl();
        JsonObject jObject = jsonElement.getAsJsonObject();
        myInterface.setValue1(jObject.get("value1").getAsLong());
        return myInterface;
    }
}

public class GsonFactory {
    public Gson create() {
        return new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapter(MyInterface.class, new MyInterfaceDeserializer())
                .create();
    }
}

另一种选择
使用 RuntimeTypeAdapterFactory 但此解决方案需要 json 中的额外 type 属性 来定义确切的子类型,请参阅文档。
示例:

    public Gson create() {
        RuntimeTypeAdapterFactory<MyInterface> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory.of(MyInterface.class).registerSubtype(MyInterfaceImpl.class, "MyInterfaceImpl");
        return new GsonBuilder()
                .setPrettyPrinting()
                .registerTypeAdapterFactory(runtimeTypeAdapterFactory)
                .create();
    }

JSON 必须包含类型字段:

{
  myList: [
    {
      value1: 8,
      type: MyInterfaceImpl
    }
  ]
}

请注意 gson-extras library required for that option. This artifact is located at CronApp 存储库。