杰克逊:用类似XML的列表反序列化JSON

时间:2014-03-20 13:08:25

标签: json jackson

我无法控制的服务是在有一个项目时向我发送看起来像这样的JSON:

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

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

{ items: null }

......当有两件或两件以上的物品时,就像这样:

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

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

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

...并且已经将结果抛给XML-&gt; JSON转换器,而没有过多关注结果。

使用Jackson,我可以处理&#34;有时为null,有时是对象,有时是数组&#34;通过使用DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY配置我的ObjectMapper来解决Jackson问题。

我可以通过使用字段Items定义List<Item> item类来处理双层结构。

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

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

2 个答案:

答案 0 :(得分: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"}]}

答案 1 :(得分:0)

通常,处理映射的最简单方法是反映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<Item>的映射。

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