How to wrap a List as top level element in JSON generated by Jackson

前端 未结 2 471
死守一世寂寞
死守一世寂寞 2020-12-16 04:58

I am running into a problem where I am trying to include a List as the root node, but I can\'t seem to be able to get this. Let me explain. Let\'s say we have a class \"Test

相关标签:
2条回答
  • 2020-12-16 05:20

    I'd expect the basic idea to be something like:

    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); 
    }
    
    0 讨论(0)
  • 2020-12-16 05:33

    Unfortunately, even with the WRAP_ROOT_VALUE feature enabled you still need extra logic to control the root name generated when serializing a Java collection (see this answer for details why). Which leaves you with the options of:

    • using a holder class to define the root name
    • using a map.
    • using a custom ObjectWriter

    Here is some code illustrating the three different options:

    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()));
        }
    }
    

    Output:

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

    Using an ObjectWriter is very convenient - just bare in mind that all top level objects serialized with it will have the same root name. If thats not desirable then use a map or holder class instead.

    0 讨论(0)
提交回复
热议问题