Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 344
Gregg Avatar asked Apr 20 '16 14:04

Gregg


2 Answers

SpringBoot use Jackson as json tool, so this will work well:

@JsonTypeName("stores")
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
public class stores { 
    ...
}
like image 88
lizhipeng Avatar answered Oct 09 '22 22:10

lizhipeng


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 Kackson

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);
}
like image 39
Pascal Avatar answered Oct 10 '22 00:10

Pascal