【问题标题】:Deserialize into dynamic Java types反序列化为动态 Java 类型
【发布时间】:2017-11-06 16:07:24
【问题描述】:

我今天的问题是我有这种 JSON, 有一个对象数组,每个对象都有 两个属性:typevalue

[{
    "type": "Boolean",
    "value": false
}, {
    "type": "String[]",
    "value": ["one", "two", "three"]
}]

如您所见,value 类依赖于type。 我可能有一个type: MyClass,其中value 是一个复杂对象。

我希望能够反序列化这个数组(并将其序列化回来 之后转换成 JSON)。

我开始研究Gson 库,但我可能随时更改。 根据我的阅读,我只知道一种方法:

public class MyExtractor implements JsonDeserializer<Object> {
    @Override
    public Object deserialize(JsonElement elem, Type jtype,
            JsonDeserializationContext jdc) throws JsonParseException {
        // elem is an object
        JsonObject obj = elem.getAsJsonObject();
        String type = obj.get("type").getAsString();
        // Return a different kind of Object depending on the 'type' attr
        switch (type) {
        case "Boolean":
            Boolean bool = obj.get("value").getAsBoolean();
            return bool;
        case "String[]":
            JsonArray data = obj.get("value").getAsJsonArray();
            List<String> list = new ArrayList<String>();
            for (JsonElement item : data) {
                list.add(item.getAsString());
            }
            return list;
        }
    }
}

在这里我添加代码以将每个type 关联到其适当的类。 这可能会按我的意愿工作,但是有更好的方法吗? 这最终需要相当多的模板。

此外,反序列化的项目被转换为 Object 所以我不 无需阅读他们的getClass() 和 把它们扔回去,我不能从 overloading 中受益。

是否有针对该问题采用不同方法的库?

【问题讨论】:

  • 你可以试试看dynamic code generation
  • 你能改变json吗?
  • @DavideLorenzoMARINO 是的,我可以访问生成和使用此 JSON 的 JavaScript。理论上我可以用它做任何事情。在 JS 中,将所有对象放在一个数组中很方便,但这可以改变(在 JS 中合并多个数组非常容易)。我猜这会使反序列化更容易。现在,'type' 属性在唯一数组中是相关的,因为有 4 个不同的“复杂类”具有自定义属性和行为。

标签: java json gson deserialization


【解决方案1】:

如果您可以将原始 json 更改为:

[{
    "type": "Boolean",
    "value": false
}, {
    "type": "String[]",
    "value": ["one", "two", "three"]
}]

[false, ["one", "two", "three"]]

您可以简单地将其反序列化为

String jsonString = ...
Object[] result = new Gson().fromJson(jsonString, Object[].class);

这适用于每种标准类型(StringBooleanInteger...),对于自定义类,它将创建一个 Map


例如,如果jsonString 有内容

["testString", false, {"name":"Davide", "surname":"Marino"}]

它将生成一个对象数组:

  • String testString 在第一位
  • Booleanfalse在第二位
  • Map 具有属性 name(值为 Davide)和 surname(值为 Marino)第三名

如果您不需要处理现有的 java 类,但您有 3 4 个自定义类,则可以使用多态反序列化。

基本上你需要创建一个自定义接口(或基类)并实现(或扩展)它。 要查看更完整的示例,请参阅接受的答案

Gson serialize a list of polymorphic objects

【讨论】:

    【解决方案2】:

    您可以尝试 jolt json 转换器,然后使用标准映射器之一(Jackson、gson 等)

    【讨论】:

      【解决方案3】:

      pretius-jddl 能够根据特定字段的存在或值进行反序列化。自述文件中的示例几乎正是您想要的。

      在您的情况下,您必须根据 type 的值创建两个区分反序列化的规则:

      DynamicObjectDeserializer deserializer = new DynamicObjectDeserializer();
      
      deserializer.addRule(DeserializationRuleFactory.typeByFieldValue(1, 
          "type", "Boolean", Boolean.class));
      deserializer.addRule(DeserializationRuleFactory.typeByFieldValue(1, 
          "type", "String[]", String[].class));
      

      有更多关于这个blog post about jddl的信息

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-03
        • 2015-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多