I've been trying to apply what's on http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html)\, and applying it to what I've been working on. While it works great for what I'll call "outer" elements in the JSON structure, I'm encountering a frustrating problem that there hasn't been much documentation.
First, my code is somewhat like the following:
interface Parameters {
// Couple random properties -- no problem here
SubTypeParameters getSubTypeParameters(); // where SubTypeParameters are polymorphic
void setSubTypeParameters(SubTypeParameters value);
}
@JsonSubTypes({
@JsonSubTypes.Type(name = "a", value = ASubTypeParameters.class),
@JsonSubTypes.Type(name = "b", value = BSubTypeParameters.class)
})
interface SubTypeParameters {
String getValue();
void setValue(String value);
}
@JsonTypeName(value = "a")
class ASubTypeParameters implements SubTypeParameters {
// getter/setter implemented
}
@JsonTypeName(value = "b")
class BSubTypeParameters implements SubTypeParameters {
// getter/setter implemented
}
What I'm trying to do is to implement the 6th option in the linked blog post so that the JSON will appear like the following (notice no 'type' element specified--it's based off context):
{
// other properties corresponding to the Parameters object
"a": {
"value": "value for a"
}
}
or
{
// other properties corresponding to the Parameters object
"b": {
"value": "value for b"
}
}
What I'm trying to avoid is introducing another "type" variables into the JSON object. Rather, I would prefer to use the context provided into either of the above JSON examples to know that I should be building an ASubTypeParameters or BSubTypeParameters object based on the presence of "a" or "b".
The fun thing is that the Parameters class/object is also polymorphic, so I have registered its own custom deserializer class like the following:
ObjectMapper mapper = new ObjectMapper();
StdDeserializer<Parameters> parameterDeserializer = new ParameterDeserializer();
SimpleModule module = new SimpleModule ( ... ); // simplifying this--no problem here
module.addDeserializer(Parameters.class, parameterDeserializer);
mapper.registerModule(module);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
However, when the above deserializer tries to deserialize either of the above JSON examples, it will get to the part where it tries to deserialize "a" or "b", and indicates that it doesn't know how to handle those properties (UnrecognizedPropretyException if I remove the fail on unknown properties line). My question really boils down to: What am I missing (annotation or otherwise)?
I've also tried adding:
mapper.registerSubtypes(ASubTypeParameters.class, BSubTypeParameters.class)
as well as
mapper.registerSubtypes(
new NamedType(ASubTypeParameters.class, "a"),
new NamedType(BSubTypeParameters.class, "b")
);
to no avail.
I know that I'm getting fairly close, and my guess is that I need to write some sort of custom subtype handler, but the documentation seems to be lacking for what I would like to do (especially when you're deserializing a polymorphic type/class that also contains a polymorphic element).