如何将List包装为Jackson生成的JSON中的顶级元素

时间:2013-04-15 18:58:33

标签: java json jackson

我遇到了一个问题,我试图将List包含为根节点,但我似乎无法得到它。让我解释。假设我们有一个“TestClass”类

class TestClass{
    String propertyA;       
}

现在,在一些实用方法中,这就是我的工作

String utilityMethod(){
   List<TestClass> list = someService.getList();
   new ObjectMapper().writeValueAsString(list); 
}

我想用JSON获取的输出是

{"ListOfTestClasses":[{"propertyA":"propertyAValue"},{"propertyA":"someOtherPropertyValue"}]}

我尝试过使用

objMapper.getSerializationConfig().set(Feature.WRAP_ROOT_VALUE, true);

但是,我似乎仍然没有做对。

现在,我正在创建一个Map&lt; String,TestClass&gt;我写这篇文章是为了实现我想要做的事情,但是这很有效但很明显这是一个黑客行为。有人可以帮我一个更优雅的解决方案吗?感谢

2 个答案:

答案 0 :(得分:15)

不幸的是,即使启用了WRAP_ROOT_VALUE功能,您仍然需要额外的逻辑来控制序列化Java集合时生成的根名称(有关详细信息,请参阅this answer)。这使您可以选择:

  • 使用holder类定义根名称
  • 使用地图。
  • 使用自定义ObjectWriter

以下是一些说明三种不同选项的代码:

public class TestClass {
    private String propertyA;

    // constructor/getters/setters
}

public class TestClassListHolder {

    @JsonProperty("ListOfTestClasses")
    private List<TestClass> data;

    // constructor/getters/setters
}

public class TestHarness {

    protected List<TestClass> getTestList() {
        return Arrays.asList(new TestClass("propertyAValue"), new TestClass(
                "someOtherPropertyValue"));
    }

    @Test
    public void testSerializeTestClassListDirectly() throws Exception {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
        System.out.println(mapper.writeValueAsString(getTestList()));
    }

    @Test
    public void testSerializeTestClassListViaMap() throws Exception {
        final ObjectMapper mapper = new ObjectMapper();
        final Map<String, List<TestClass>> dataMap = new HashMap<String, List<TestClass>>(
                4);
        dataMap.put("ListOfTestClasses", getTestList());
        System.out.println(mapper.writeValueAsString(dataMap));
    }

    @Test
    public void testSerializeTestClassListViaHolder() throws Exception {
        final ObjectMapper mapper = new ObjectMapper();
        final TestClassListHolder holder = new TestClassListHolder();
        holder.setData(getTestList());
        System.out.println(mapper.writeValueAsString(holder));
    }

    @Test
    public void testSerializeTestClassListViaWriter() throws Exception {
        final ObjectMapper mapper = new ObjectMapper();
        final ObjectWriter writer = mapper.writer().withRootName(
                "ListOfTestClasses");
        System.out.println(writer.writeValueAsString(getTestList()));
    }
}

输出:

  

{ “的ArrayList”:[{ “propertyA”: “propertyAValue”},{ “propertyA”: “someOtherPropertyValue”}]}
  { “ListOfTestClasses”:[{ “propertyA”: “propertyAValue”},{ “propertyA”: “someOtherPropertyValue”}]}
  { “ListOfTestClasses”:[{ “propertyA”: “propertyAValue”},{ “propertyA”: “someOtherPropertyValue”}]}
  { “ListOfTestClasses”:[{ “propertyA”: “propertyAValue”},{ “propertyA”: “someOtherPropertyValue”}]}

使用ObjectWriter非常方便 - 请记住,使用它序列化的所有顶级对象都具有相同的根名称。如果那不可取,那么请改用地图或持有人类。

答案 1 :(得分:1)

我希望基本的想法是这样的:

class UtilityClass {
    List listOfTestClasses;
    UtilityClass(List tests) {
        this.listOfTestClasses = tests;
    }
}

String utilityMethod(){
    List<TestClass> list = someService.getList();
    UtilityClass wrapper = new UtilityClass(list);
    new ObjectMapper().writeValueAsString(wrapper); 
}