I am writing a custom deserializer and not sure how to best handle the following case:
I am deserializing something that looks like this:
{
"someProp": {
"name": "some string"
"value": ****** can be anything here, including string, number, object, etc. ******
}
}
The object I am mapping this to has this:
public class ObjectToMapTo {
String name;
Object value;
}
In my code, I have the JsonNode
that represents the someProp
field. I can obviously extract the JsonNode
of the name
and easily convert it to String
with JsonNode.asText()
.
However, how do I deal with the value
? JsonNode
does NOT have a method for asObject()
. Surprisingly, it only has isObject()
. Do I have to go through a switch
statement to figure out what type of of a thing it is just so I can call the correct method like asLong()
or asText()
?
But even if I do the switch
statement, what if the nodeType
is Object
. Then what? How do I get that JsonNode
to just be a regular Java Map
like it would regularly if I were to use the ObjectMapper
without a custom deserializer?
I am afraid you have to do some custom deserializing and switching/iffing here.
JsonNode does NOT have a method for asObject(). Surprisingly, it only has isObject().
Yes. It is not a problem to determine if the value is an object since object nodes start with {
. But to what specific class instance it can be constructed is impossible to guess. That should not be surprising.
what if the nodeType is Object. Then what? How do I get whatever is specified for value in JSON
If there was a field - say type
- that tells the type you could do it easily in your custom deserializer. So if you have power to add it then you could give there the whole class name to instantiate to in your deserializer.
Otherwise I think the best you can do would be to instantiate arbitrary object as an instance of a Map
or just as a TreeNode
.
You could annotate field value
for the deserialiser like (so not the parent):
@Getter @Setter
public class ObjectToMapTo {
private String name;
@JsonDeserialize(using = MyDeserializer.class)
private Object value;
}
In your deserializer after you have checked that it is not array nor value, something like:
Object o;
TreeNode valueTreeNode = jp.readValueAsTree();
// check if array or valueNode
// but if is object
ObjectMapper om = new ObjectMapper();
o = om.treeToValue(valueTreeNode, Map.class);
return o;