Jackson framework provides annotation based approach to emit the type information during serialization process.
I do not want to use @JsonSubTypes annotation in my super class(Animal).
Instead I want to tell my SubClasses i.e Dog and Elephant that Animal is their parent.
Is there any approach to do so without using annotation in Animal class.
If yes, please provide example of to do the same if possible.
Following is case which I am trying to resolve.JSON which "test" receives, contains "type" field as "dog" or "elephant".
I want to register these two classes as subtypes of "Animal" class but don't want to use @JsonSubTypes in Animal.
Any help would be appreciated. Thanks in advance.
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
abstract class Animal(){
private String sound;
private String type;
//getters and setters
}
@JsonTypeName("dog")
Class Dog extends Animal(){
//some attributes.
//getters and setters
}
@JsonTypeName("elephant")
Class Elephant extends Animal(){
//some attributes.
//getters and setters
}
@Controller
public class MyController {
//REST service
@RequestMapping( value = "test")
public @ResponseBody String save(@RequestBody Animal animal){
System.out.println(animal.getClass());
return success;
}
}
ObjectMapper is the most important class in Jackson API that provides readValue() and writeValue() methods to transform JSON to Java Object and Java Object to JSON. ObjectMapper class can be reused and we can initialize it once as Singleton object.
You definitely don't need all those @jsonProperty . Jackson mapper can be initialized to sereliazie/deserialize according to getters or private members, you of course need only the one you are using. By default it is by getters.
@JsonProperty is used to mark non-standard getter/setter method to be used with respect to json property.
Jackson can't deserialize into private fields with its default settings. Because it needs getter or setter methods.
You can use the Moonwlker library.
With it, you can create an ObjectMapper like this:
ObjectMapper objectMapper = new ObjectMapper();
MoonwlkerModule module =
MoonwlkerModule.builder()
.fromProperty("type").toSubclassesOf(Animal.class)
.build();
objectMapper.registerModule(module);
And then use that mapper to (de)serialize. The Moonwlker website contains more details and configuration options.
This answer will help in achieving what you want, but in a slightly different way. Create a separate class with necessary configuration and register it as the serialization/deserialization configuration class for Animal class as below:
Configuration Class:
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@Type(value = Elephant.class, name = "cat"),
@Type(value = Dog.class, name = "dog") })
abstract class PolymorphicAnimalMixIn {
//Empty Class
}
To serialize or deserialize:
ObjectMapper mapper = new ObjectMapper();
mapper.getDeserializationConfig().addMixInAnnotations(Animal.class, PolymorphicAnimalMixIn.class);
mapper.getSerializationConfig().addMixInAnnotations(Animal.class, PolymorphicAnimalMixIn.class);
//Sample class with collections of Animal
class Zoo {
public Collection<Animal> animals;
}
//To deserialize
Animal animal = mapper.readValue("string_payload", Zoo.class);
//To serialize
Animal animal = mapper.writeValueAsString(zoo);
Reference credit: example 5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With