I would like to be able to convert a generic Object in a request to a custom object that I have built using Spring Boot and Jackson.
For example, say I have the following controller method:
@RequestMapping(value = "/user/action", method = RequestMethod.POST)
public String processAction(@RequestBody Request theRequest){
return "Success";
}
Now the Request object looks like this:
public class Request {
public Request(){
}
private String action;
private Object actionRequest;
//getters/setters
The actual actionRequest can be any Object (e.g. Boolean, String, or a custom built one).
So say I have a custom built ActionA class:
public class ActionA {
public ActionA(){
}
private int actionAInfo;
//getters/setters
}
If I invoke my controller with a POST and a payload of
{"action": "startEstimate", "actionRequest":true}
when it reaches the method, the 'actionRequest' is already converted to a boolean.
However, if I provide the payload
{"action": "startEstimate", "actionRequest": {"actionAInfo": 5}}
the 'actionRequest' is just converted to a HashMap with key of 'actionAInfo' and value of '5'.
How can I configure Spring Boot/Jackson to create the ActionA object?
One workaround I have seen is to instead of having Object in the Request, use ObjectNode. Then do something similar to
ObjectMapper om = new ObjectMapper();
ActionA actionA = om.convertValue(theRequest.getActionRequest(), ActionA.class);
However, this does not expand as I add more actions because I would need to know the type before I attempt to build it.
I have also attempted a solution presented here Custom JSON Deserialization with Jackson
and it does not seem to be working. I have created a new ActionADeserializer
public class ActionADeserializer extends JsonDeserializer<ActionA> {
@Override
public ActionA deserialize(JsonParser jp, DeserializationContext ctxt) throws
IOException,
JsonProcessingException {
return jp.readValueAs(ActionA.class);
}
}
and altered ActionA class to have
@JsonDeserialize(using = ActionADeserializer.class)
public class ActionA
When I submit the payload
{"action": "startEstimate", "actionRequest": {"actionAInfo": 5}}
it still creates the HashMap instead of the ActionA object. I set a breakpoint in the deserializer and do not even see it being invoked.