Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rename root key in JSON serialization with Jackson

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:

  • Jackson : custom collection serialization to JSON
  • How do I rename the root key of a JSON with Java Jackson?
  • Jackson : custom collection serialization to JSON

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

like image 802
user2266861 Avatar asked Apr 10 '13 21:04

user2266861


People also ask

How do I ignore a root element in JSON?

How to ignore parent tag from json?? String str = "{\"parent\": {\"a\":{\"id\": 10, \"name\":\"Foo\"}}}"; And here is the class to be mapped from json. (a) Annotate you class as below @JsonRootName(value = "parent") public class RootWrapper { (b) It will only work if and only if ObjectMapper is asked to wrap.

What is JSON root element?

According to the modified Backus-Naur-Form on the right side pane of http://json.org/ the root element of a JSON data structure can be any of these seven types/values: Object Array String Number true false null.

What is JsonProperty annotation?

The @JsonProperty annotation is used to map property names with JSON keys during serialization and deserialization. By default, if you try to serialize a POJO, the generated JSON will have keys mapped to the fields of the POJO.

How do you serialize an object to JSON Jackson in Java?

Converting Java object to JSON In it, create an object of the POJO class, set required values to it using the setter methods. Instantiate the ObjectMapper class. Invoke the writeValueAsString() method by passing the above created POJO object. Retrieve and print the obtained JSON.


3 Answers

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);
like image 92
Perception Avatar answered Oct 19 '22 13:10

Perception


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"}]}
like image 45
Vaibhav Avatar answered Oct 19 '22 12:10

Vaibhav


@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;
    }
}
like image 12
Jose Montestruque Avatar answered Oct 19 '22 13:10

Jose Montestruque