Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @RequestBody containing a list of different types (but same interface)

Let's say that I have a domain class :

    public class Zoo{         private List<Animal> animals;         .... 

where an Animal is an interface with different implementations (Cat,Dog). Let's say that I want to be able to save a Zoo object :

    @RequestMapping(value = "/zoo", method = RequestMethod.POST)     public @ResponseBody void save(@RequestBody Zoo zoo) {     .... 

and I want to send a json - something like :

    {         animals:[             {type:'Cat', whiskers-length:'3'},             {type:'Dog', name:'Fancy'}         ]     } 

How can I tell spring MVC to map animal to Cat type when type=='Cat' and to map it to a Dog class when type=='Dog'?

like image 802
Viktor K. Avatar asked Jun 22 '13 04:06

Viktor K.


People also ask

What is difference between @RequestBody and @ModelAttribute?

@ModelAttribute is used for binding data from request param (in key value pairs), but @RequestBody is used for binding data from whole body of the request like POST,PUT.. request types which contains other format like json, xml.

Does spring @RequestBody support the GET method?

Thanks. spring v5. 3.6 supports request body with GET.

What is @ResponseBody annotation in spring?

The @ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object. When you use the @ResponseBody annotation on a method, Spring converts the return value and writes it to the HTTP response automatically.

Can RequestBody be optional?

With Spring's latest version, if you use @RequestBody annotation, it makes client to send body all the time without making it optional.


2 Answers

You should use the Jackson annotations @JsonTypeInfo and @JsonSubTypes to achieve polymorphic json. The annotations go on the Animal base class.

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes({@JsonSubTypes.Type(value = Dog.class, name = "Dog"),         @JsonSubTypes.Type(value = Cat.class, name = "Cat")}) public abstract class Animal {  } 
like image 84
nicholas.hauschild Avatar answered Sep 17 '22 11:09

nicholas.hauschild


There is a simpler annotation out now:

@JsonRootName("dog") public class Dog extends Animal {...} 

The reference to the annotation can be found on fasterxml.github

like image 34
Prancer Avatar answered Sep 16 '22 11:09

Prancer