Gson – 基于字段值反序列化为特定对象类型

我想基于type字段值将json对象反序列化为特定类型的对象(使用Gson库),例如:

 [ { "type": "type1", "id": "131481204101", "url": "http://something.com", "name": "BLAH BLAH", "icon": "SOME_STRING", "price": "FREE", "backgroundUrl": "SOME_STRING" }, { .... } ] 

因此, type字段将具有不同(但已知)的值。 基于该值,我需要将该json对象反序列化为适当的模型对象,例如:Type1Model,Type2Model等。我知道我可以在反序列化之前通过将其转换为JSONArray ,迭代它并解析应该反序列化的类型来轻松地做到这一点。至。 但我认为这是一种丑陋的方法,我正在寻找更好的方法。 有什么建议么?

您可以实现JsonDeserializer并在将Json值解析为Java实例时使用它。 我会尝试用一个代码来展示它,它会给你一个想法:

1)定义您的自定义JsonDeserializer类,它通过传入的json值的id属性创建不同的类实例:

 class MyTypeModelDeserializer implements JsonDeserializer { @Override public MyBaseTypeModel deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); JsonElement jsonType = jsonObject.get("type"); String type = jsonType.getAsString(); MyBaseTypeModel typeModel = null; if("type1".equals(type)) { typeModel = new Type1Model(); } else if("type2".equals(type)) { typeModel = new Type2Model(); } // TODO : set properties of type model return typeModel; } } 

2)为不同的java对象实例定义一个基类:

 class MyBaseTypeModel { private String type; // TODO : add other shared fields here } 

3)定义扩展基类的java对象类的不同实例:

 class Type1Model extends MyBaseTypeModel { // TODO: add specific fields for this class } class Type2Model extends MyBaseTypeModel { // TODO: add specific fields for this class } 

4)在将json值解析为bean时使用这些类:

 GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(MyBaseTypeModel.class, new MyTypeModelDeserializer()); Gson gson = gsonBuilder.create(); MyBaseTypeModel myTypeModel = gson.fromJson(myJsonString, MyBaseTypeModel.class); 

我现在无法测试它,但我希望你能得到这个想法。 此链接也非常有用。

使用https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java

然后配置它

 public static final class JsonAdapterFactory extends RuntimeTypeAdapterFactory { public JsonAdapterFactory() { super(MyBaseType.class, "type"); registerSubtype(MySubtype1.class, "type1"); registerSubtype(MySubtype2.class, "type2"); } } 

并添加注释:

@JsonAdapter(MyBaseType.JsonAdapterFactory.class)

到MyBaseType

好多了。

@ stephane-k的答案有效,但有点令人困惑,可以改进(见他的回答评论)

将https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java复制到您的项目中。 (没关系;这些课程设计为复制/粘贴https://github.com/google/gson/issues/845#issuecomment-217231315 )

安装模型inheritance:

 // abstract is optional abstract class BaseClass { } class Type1Model extends BaseClass { } class Type2Model extends BaseClass { } 

设置GSON或更新现有的GSON:

 RuntimeTypeAdapterFactory typeAdapterFactory = RuntimeTypeAdapterFactory .of(BaseClass.class, "type") .registerSubtype(Type1Model.class, "type1") .registerSubtype(Type2Model.class, "type2"); Gson gson = new GsonBuilder().registerTypeAdapterFactory(typeAdapterFactory) .create(); 

将JSON反序列化为基类:

 String jsonString = ... BaseClass baseInstance = gson.fromJson(jsonString, BaseClass.class); 

baseInstance将是Type1ModelType2Model实例。

从这里,您可以编码到接口或检查instanceof和强制转换。