Gregg Gregg - 2 months ago 101
JSON Question

spring-boot json root name

I'm using spring-boot 1.3.3 and trying to figure out how to have root names on JSON serialization. For example, I would like...

{ stores: [
{
id: 1,
name: "Store1"
},
{
id: 2,
name: "Store2"
}]
}


but instead I am getting

[
{
id: 1,
name: "Store1"
},
{
id: 2,
name: "Store2"
}
]


I've been looking at
@JsonRootName
and customizing the
Jackson2ObjectMapperBuilder
config but to no avail. In grails, this is pretty simple with Json Views and I was trying also to see how that translated directly to spring-boot but still can't seem to figure it out.

I realize this is similar to this question but I feel like in the context of Spring (boot) it might be applied differently and would like to know how.

Answer

Solution 1: Jackson JsonRootName

I've been looking at @JsonRootName and customizing the Jackson2ObjectMapperBuilder config but to no avail.

What are your errors with @JsonRootName and the Jackson2ObjectMapperBuilder?

This works in my spring boot (1.3.3) implementation:

Jackson configuration Bean

@Configuration
public class JacksonConfig {

    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToEnable(SerializationFeature.WRAP_ROOT_VALUE); // enables wrapping for root elements
       return builder;
    }
}

Reference: Spring Documentation - Customizing the Jackson ObjectMapper

Add @JsonRootElement to your response entity

@JsonRootName(value = "lot")
public class LotDTO { ... }

Json Result for HTTP-GET /lot/1

{
  "lot": {
    "id": 1,
    "attributes": "...",
    }
}

At least this works for a response with one object.

I haven't figured out how to customize the root name in a collection. @Perceptions' answer might help How to rename root key in JSON serialization with Jackson


EDIT

Solution 2: Without Jackson configuration

since I couldn't figure out how to customize the json root name in a collection with jackson, I adapted the answer from @Vaibhav (see 2):

Custom Java Annotation

@Retention(value = RetentionPolicy.RUNTIME)
public @interface CustomJsonRootName {
    String singular(); // element root name for a single object
    String plural(); // element root name for collections
}

Add annotation to DTO

@CustomJsonRootName(plural = "articles", singular = "article")
public class ArticleDTO { // Attributes, Getter and Setter }

Return a Map as result in Spring Controller

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Map<String, List<ArticleDTO>>> findAll() {
  List<ArticleDTO> articles = articleService.findAll();

  if (articles.isEmpty()) {
      return new ResponseEntity<>(HttpStatus.NO_CONTENT);
  }
  Map result = new HashMap();
  result.put(ArticleDTO.class.getAnnotation(CustomJsonRootName.class).plural(), articles);
  return new ResponseEntity<>(result, HttpStatus.OK);
 }