How to rename root key in JSON serialization with

2020-01-29 05:20发布

I am using Jackson for JSON serialization of a list of objects.

Here is what I get:

{"ArrayList":[{"id":1,"name":"test name"}]}

But I want this :

{"rootname":[{"id":1,"name":"test name"}]} // ie showing the string I want as the root name.

Below is my approach to this:

Interface:

public interface MyInterface {
    public long getId();
    public String getName();
}

Implementation class:

@JsonRootName(value = "rootname")
public class MyImpl implements MyInterface {
    private final long id;
    private String name;

    public MyImpl(final long id,final name) {
        this.id = id;
        this.name = name;
    }

   // getters     
}

JSon serialization:

public class MySerializer {
    public static String serializeList(final List<MyInterface> lists) {
        //check for null value.Throw Exception
        final ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
        return mapper.writeValueAsString(lists);
    }
}

Test:

final List<MyInterface> list = new ArrayList<MyImpl>();
MyImpl item = new MyImpl(1L,"test name");
list.add(item);
final String json = MySerializer.serializeList(list);
System.out.println(json);

Here is what I get:

{"ArrayList":[{"id":1,"name":"test name"}]}

But I want this :

{"rootname":[{"id":1,"name":"test name"}]} // ie showing the string I want as the root     name.

I have tried all suggested solutions I could find but failed to achieve my goal. I have looked at:

Or am I missing something? I am using jackson 1.9.12 for this. Any help in this regard is welcome.

4条回答
我只想做你的唯一
2楼-- · 2020-01-29 05:52
@JsonTypeName("usuarios")
@JsonTypeInfo(include= JsonTypeInfo.As.WRAPPER_OBJECT,use= JsonTypeInfo.Id.NAME)
public class UsuarioDT extends ArrayList<Usuario> {

    @JsonProperty("rowsAffected")
    private Integer afectados;

    public Integer getAfectados() {
        return afectados;
    }

    public void setAfectados(Integer afectados) {
        this.afectados = afectados;
    }
}
查看更多
够拽才男人
3楼-- · 2020-01-29 05:53

You need to use this annotation at the top of the class

@JsonTypeName("rootname")

查看更多
兄弟一词,经得起流年.
4楼-- · 2020-01-29 05:58

Well, by default Jackson uses one of two annotations when trying to determine the root name to be displayed for wrapped values - @XmlRootElement or @JsonRootName. It expects this annotation to be on the type being serialized, else it will use the simple name of the type as the root name.

In your case, you are serializing a list, which is why the root name is 'ArrayList' (simple name of the type being serialized). Each element in the list may be of a type annotated with @JsonRootName, but the list itself is not.

When the root value you are trying to wrap is a collection then you need some way of defining the wrap name:

Holder/Wrapper Class

You can create a wrapper class to hold the list, with an annotation to define the desired property name (you only need to use this method when you do not have direct control of the ObjectMapper/JSON transformation process):

class MyInterfaceList {
    @JsonProperty("rootname")
    private List<MyInterface> list;

    public List<MyInterface> getList() {
        return list;
    }

    public void setList(List<MyInterface> list) {
        this.list = list;
    }
}

final List<MyInterface> lists = new ArrayList<MyInterface>(4);
lists.add(new MyImpl(1L, "test name"));
MyInterfaceList listHolder = new MyInterfaceList();
listHolder.setList(lists);
final String json = mapper.writeValueAsString(listHolder);

Object Writer

This is the preferable option. Use a configured ObjectWriter instance to generate the JSON. In particular, we are interested in the withRootName method:

final List<MyInterface> lists = new ArrayList<MyInterface>(4);
lists.add(new MyImpl(1L, "test name"));
final ObjectWriter writer = mapper.writer().withRootName("rootName");
final String json = writer.writeValueAsString(lists);
查看更多
Emotional °昔
5楼-- · 2020-01-29 06:05

I know, I am late , but I have better approach which don't require Holder/Wrapper Class. It picks root key from annotation.

package com.test;

import com.fasterxml.jackson.annotation.JsonRootName;


@JsonRootName("Products")
public class ProductDTO {
    private String name;
    private String description;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

Here is test class:-

package com.test;

import java.io.IOException;
import java.util.ArrayList;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;


public class ProductDTOTestCase {
    @Test
    public void testPersistAndFindById() throws JsonGenerationException, JsonMappingException, IOException {
        ObjectMapper mapper = new ObjectMapper();
        ProductDTO productDTO = new ProductDTO();
        productDTO.setDescription("Product 4 - Test");

        ArrayList<ProductDTO> arrayList = new ArrayList<ProductDTO>();
        arrayList.add(productDTO);

        String rootName = ProductDTO.class.getAnnotation(JsonRootName.class).value();
        System.out.println(mapper.writer().withRootName(rootName).writeValueAsString(arrayList));

    }


}

It will give following output

{"Products":[{"name":null,"description":"Product 4 - Test"}]}
查看更多
登录 后发表回答