当前位置: 首页 > 知识库问答 >
问题:

用Jackson将可变(原语/对象)JSON属性反序列化为对象

葛哲彦
2023-03-14

给定一个JSON对象,它具有可变属性(例如标签),可以是原始值(例如字符串)或对象。假设的用例可以是标签多元化翻译的包装器:

{
   "label": "User name"
}

或者

{
   "label": {
       "one": "A label",
       "other": "The labels"
   }
}

目标是使Jackson反序列化始终在Java端返回固定结构。因此,如果给定原语值,它总是转换为目标POJO的某个属性(例如其他),即:

public class Translations {
   @JsonDeserialize(using = PluralizedTranslationDeserializer.class)
   public PluralizedTranslation label;
}

public class PluralizedTranslation {
   public String one;
   public String other;  // used as default fields for primitive value
}

目前,该问题通过使用自定义JsonDeserializer来解决,它检查属性是否为原语:

public class PluralizedTranslationDeserializer extends JsonDeserializer {
    @Override
    public PluralizedTranslation deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        PluralizedTranslation translation;

        if (node.isTextual()) {
            translation = new PluralizedTranslation();
            translation.other = node.asText();
        } else {
            translation = oc.treeToValue(node, PluralizedTranslation.class);
        }

        return translation;
    }
}

是否有一种更优雅的方法来处理可变JSON属性,而不需要在节点级别操作的解码器?

共有1个答案

闾丘永春
2023-03-14

您可以使标签setter更通用,并添加一些处理这两种情况的逻辑。

public class Translations {
    // Fields omitted.

    @JsonProperty("label")
    public void setLabel(Object o) {
        if (o instanceof String) {
            // Handle the first case
        } else if (o instanceof Map) {
            // Handle the second case
        } else {
            throw new RuntimeException("Unsupported");
        }
    }
}

替代解决方案,将工厂方法放在PluralizedTranslation类中,使Translationsclass不受影响:

public class PluralizedTranslation {
    public String one;
    public String other;  // used as default fields for primitive value

    @JsonCreator
    private PluralizedTranslation(Object obj) {
        if (obj instanceof Map) {
            Map map = (Map) obj;
            one = (String) map.get("one");
            other = (String) map.get("other");
        } else if (obj instanceof String) {
            other = (String) obj;
        } else {
            throw new RuntimeException("Unsupported");
        }
    }
} 

请注意,构造函数可以标记为< code>private,以防止意外使用。

 类似资料:
  • 我需要反序列化以下json: 将它的< code>id属性设置为< code>foo_id json属性。 我需要在自定义反序列化程序中执行此操作。实现这一点最简单的方法是什么? 我想以某种方式将json“转换”为 然后将此委托给杰克逊。 在本例中,对象的类型为Foo,但其他对象可能不属于此类。另外,在本例中,json是一个数字,但如果它也是一个字符串,我希望支持。所以,我需要一种通用的方法来做到

  • 鉴于这种反应: 我怎样才能将数据属性反序列化为像这样的 MapDTO 我已经尝试使用自定义反序列化器,但是按名称获取所有属性,然后基于这些属性和嵌套对象创建一个新的MapDTO对象看起来很麻烦。如果结构发生变化,我必须更改反序列化器和DTO本身。让Jackson从给定的根开始进行反序列化会更容易。我使用Jackson 2.12.4到ResAs的4.4.0。我想避免创建不必要的包装类。

  • 问题内容: 我有一些具有各种属性的JSON,其中大多数是简单数据类型。但是,我在JSON中有一个属性,当我将其反序列化为C#类时,我只需要将其反序列化为字符串即可。 JSON示例: 除了将是有效的JSON对象外,“ json”对象没有任何设置结构。 因此,在上面的示例中,“ json”的值是一个JSON对象-但是当它反序列化时,我需要将它作为字符串。 因此,如果我的C#类是: 然后,如果我使用:

  • 我目前正在开发一个Java web应用程序,它使用Magento REST API公开的JSON数据。api返回的数据示例如下: 我的应用程序中有一个Java类,如下所示: 我想对数据进行反序列化,并将其转换为,但我总是得到以下错误: 这是我用来将JSON响应反序列化为ArrayList的语句行: 有人能分享一些见解吗?我看到一些例子,返回的JSON对象前面没有任何ID。那是因为我做错了什么吗?非

  • 问题内容: 使用Jackson 2,我正在寻找一种 通用的 方式将对象序列化为单个值(然后序列化它们,然后再填充该单个字段),而不必重复创建JsonSerializer / JsonDeserializer来处理每种情况。@JsonIdentityInfo批注非常接近,但由于我知道,它将始终对完整的子对象进行序列化,因此略微遗漏了该标记。 这是我想做的一个例子。给定的类: 我希望Order可以序列

  • 问题内容: 我在使用AJAX访问的Java服务器应用程序中有一个字符串。它看起来像以下内容: 当从服务器提取字符串时,是否有一种简单的方法可以将其转换为活动的JavaScript对象(或数组)?还是我必须手动拆分字符串并手动构建对象? 问题答案: 现代浏览器支持。 在不浏览器,您可以包括在库中。