Steve Powell
Steve Powell

Reputation: 26474

Using @JsonTypeInfo why can't the polymorphic field be omitted?

Here is a polymorphic field:

@JsonProperty("config")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(name = "keystone", value = KeystoneConfig.class),
    @JsonSubTypes.Type(name = "internal", value = InternalConfig.class)
})
@Nullable
abstract Configuration getConfig();

where Configuration is an interface, and type is a String field elsewhere in the structure/class.

This works fine with a response payload (something) like this:

{ "type": "internal",
  "config": { "int1": "value1" }
}

but fails with a deserialization parsing error when the config field is omitted, like this:

{ "type": "internal"
}

Normally, when fields are omitted, we get the Java default value (I expected null in this case). I wish to retain the discriminator field type, but allow the config field to be optional.

How can I get that behaviour in this case?

Upvotes: 2

Views: 1418

Answers (1)

Wilson
Wilson

Reputation: 11619

JacksonAnnotationIntrospector, JsonDeserializer and JsonTypeResolver seems do not help for your case. At the time being, I can only come up a work around by deserializing the json string with 3 step as follows:

ObjectMapper mapper = new ObjectMapper();
// 1. deserializing the json string into JsonNode
JsonNode jsonNode = mapper.readTree(json);
// 2. Add a empty node if "config" property is not found
JsonNode configNode = jsonNode.get("config");
if (jsonNode.isObject() && (configNode == null || configNode.size() == 0)) {
    ((ObjectNode) jsonNode).put("config", "");
}
// 3. Convert to desired class
mapper.treeToValue(jsonNode, Foo.class);

Upvotes: 1

Related Questions