【问题标题】:Jackson: deserialize JSON with XML-like listsJackson:使用类似 XML 的列表反序列化 JSON
【发布时间】:2014-03-20 13:08:24
【问题描述】:

当有一个项目时,我无法控制的服务会向我发送如下所示的 JSON:

{ items: {
     item: { ... }
}

...当没有项目时是这样的:

{ items: null }

...当有两个或多个项目时这样:

 { items: {
    item: [
        { ... }, 
        { ... }
    ]
    }
 }

我相信这是因为该服务旨在生成这样的 XML:

  <items>
       <item>....</item>
       <item>....</item>
  </items>

...并将结果扔到一个 XML->JSON 转换器上,而没有过多关注结果。

使用 Jackson,我可以通过使用 DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY 配置我的 ObjectMapper 来处理 Jackson 中的“有时为空,有时为对象,有时为数组”问题。

我可以通过定义带有字段List&lt;Item&gt; itemItems 类来处理两层结构。

但是,Items 类只是作为奇怪的 JSON 格式的一种解决方案。除了编写一个完整的自定义反序列化器之外,我是否可以说服杰克逊反序列化为一个对象就好像结构是:

{ items: [ { ... }, { ... } ] }

?

【问题讨论】:

    标签: json jackson


    【解决方案1】:

    看起来您有一个包含Items 属性的根对象。在这种情况下,您可以使用 @JsonUnwrapped 注释。请参阅下面的课程:

    class Root {
    
        @JsonUnwrapped
        private Items items = new Items();
    
        public Items getItems() {
            return items;
        }
    
        public void setItems(Items items) {
            this.items = items;
        }
    }
    

    简单用法:

    ObjectMapper mapper = new ObjectMapper();
    Items items = new Items();
    items.setItem(Arrays.asList(new Item(), new Item()));
    
    Root wrapper = new Root();
    wrapper.setItems(items);
    
    String json = mapper.writeValueAsString(wrapper);
    System.out.println(json);
    

    上面的程序打印:

    {"item":[{"name":"X"},{"name":"X"}]}
    

    【讨论】:

    • 谢谢 - 这就是我想要的,只是倒退。它展示了如何序列化为健全的格式。我想将奇怪的 JSON 反序列化为一个健全的对象。
    • 反序列化也可以。你可以这样做:objectMapper.readValue(json, Root.class);。你能试试吗?
    【解决方案2】:

    通常处理映射最简单的方法是在 POJO 结构中反映数据格式的结构。因此,在这种情况下,您将添加一个在功能上不必要但在映射方面需要的属性:

    public class POJO {
        public ItemHolder items;
    
        // might want convenience method for Java access, but not with getter name
        public List<Item> items() {
           return (items == null) ? null : items.item;
        }
    } 
    public class ItemHolder {
        public List<Item> item;
    }
    

    您还需要启用DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY 来处理从单个ItemList&lt;Item&gt; 的映射。

    但也许使用@JsonUnwrapped 的另一个答案也有帮助;这是另一种选择。

    【讨论】:

      猜你喜欢
      • 2018-08-15
      • 1970-01-01
      • 2020-07-07
      • 2016-08-05
      • 1970-01-01
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 2016-06-14
      相关资源
      最近更新 更多