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) 中查找字段,而不是在实现 interface
的 class
中查找字段。
有人知道怎么解决吗?
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 存储库。
我有一个 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) 中查找字段,而不是在实现 interface
的 class
中查找字段。
有人知道怎么解决吗?
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 存储库。