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

2022-09-02 02:27:53

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

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

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


答案 1

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

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

class MyTypeModelDeserializer implements JsonDeserializer<MyBaseTypeModel> {

    @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);

我现在不能测试它,但我希望你明白这个想法。此外,此链接将非常有帮助。


答案 2

@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)

安装模型继承:

// abstract is optional
abstract class BaseClass {
}

class Type1Model extends BaseClass {
}

class Type2Model extends BaseClass {
}

设置 GSON 或更新现有 GSON:

RuntimeTypeAdapterFactory<BaseClass> 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

从这里,您可以编写代码到接口或检查实例和转换。