/** Custom deserializer for sealed interface with unwrapped variants. */
class {{ class_name }}Deserializer extends StdDeserializer<{{ class_name }}> {
private static final long serialVersionUID = 1L;
{{ class_name }}Deserializer() {
super({{ class_name }}.class);
}
{% if is_adjacent and needs_content %}
/** Rejects an adjacently tagged document whose "{{ content_field_doc }}" payload is absent. */
private static com.fasterxml.jackson.databind.JsonNode requireContent(
final JsonParser parser,
final com.fasterxml.jackson.databind.JsonNode contentNode,
final String tagValue)
throws java.io.IOException {
if (contentNode == null || contentNode.isNull()) {
throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Missing '{{ content_field }}' payload for {{ class_name }} variant: " + tagValue);
}
return contentNode;
}
{% endif %}
@Override
@SuppressWarnings("PMD.CyclomaticComplexity")
public {{ class_name }} deserialize(final JsonParser parser, final DeserializationContext ctx)
throws java.io.IOException {
{% if is_external %}
final com.fasterxml.jackson.databind.JsonNode wire = parser.getCodec().readTree(parser);
if (wire.isTextual()) {
return switch (wire.asText()) {
{% for variant in variants %}
{% if variant.is_unit %}
case "{{ variant.discriminator }}" -> new {{ class_name }}.{{ variant.name }}();
{% endif %}
{% endfor %}
{% if has_untagged_string_variant %}
{% for variant in variants %}
{% if variant.is_untagged and variant.is_tuple %}
default -> new {{ class_name }}.{{ variant.name }}(wire.asText());
{% endif %}
{% endfor %}
{% else %}
default -> throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Unknown {{ class_name }} unit variant: " + wire.asText());
{% endif %}
};
}
{% if not has_external_object_variant %}
throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "{% if has_untagged_string_variant %}Untagged variant must be a string{% else %}{{ class_name }} accepts only string variants{% endif %}");
{% else %}
if (!wire.isObject() || wire.size() != 1) {
throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Expected one externally tagged {{ class_name }} variant");
}
final String tagValue = wire.fieldNames().next();
final com.fasterxml.jackson.databind.JsonNode contentNode = wire.get(tagValue);
{% endif %}
{% else %}
final ObjectNode node = parser.getCodec().readTree(parser);
final com.fasterxml.jackson.databind.JsonNode tagNode = node.get("{{ tag_field }}");
if (tagNode == null || tagNode.isNull()) {
throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Missing discriminator field: {{ tag_field }}");
}
final String tagValue = tagNode.asText();
{% if is_adjacent %}
final com.fasterxml.jackson.databind.JsonNode contentNode = node.get("{{ content_field }}");
{% else %}
node.remove("{{ tag_field }}");
{% endif %}
{% endif %}
{% if not is_external or has_external_object_variant %}
return switch (tagValue) {
{% for variant in variants %}
{% if variant.is_unit %}
{% if is_external %}
case "{{ variant.discriminator }}" -> throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Externally tagged unit variants must be strings");
{% else %}
case "{{ variant.discriminator }}" -> new {{ class_name }}.{{ variant.name }}();
{% endif %}
{% elif is_external and variant.is_untagged %}
case "{{ variant.discriminator }}" -> throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Untagged variant must be a string");
{% elif is_adjacent or is_external %}
{% if variant.is_tuple %}
case "{{ variant.discriminator }}" -> new {{ class_name }}.{{ variant.name }}(
ctx.readTreeAsValue({% if is_external %}contentNode{% else %}requireContent(parser, contentNode, tagValue){% endif %}, {{ variant.inner_type }}.class));
{% else %}
case "{{ variant.discriminator }}" -> ctx.readTreeAsValue(
{% if is_external %}contentNode{% else %}requireContent(parser, contentNode, tagValue){% endif %}, {{ class_name }}.{{ variant.name }}.class);
{% endif %}
{% elif variant.is_tuple %}
{% if variant.inner_type == "String" %}
case "{{ variant.discriminator }}" -> new {{ class_name }}.{{ variant.name }}(node.toString());
{% else %}
case "{{ variant.discriminator }}" -> new {{ class_name }}.{{ variant.name }}(ctx.readTreeAsValue(node, {{ variant.inner_type }}.class));
{% endif %}
{% else %}
case "{{ variant.discriminator }}" -> ctx.readTreeAsValue(node, {{ class_name }}.{{ variant.name }}.class);
{% endif %}
{% endfor %}
default -> {
{% if excluded_variants %}
if ({% for discriminator in excluded_variants %}{% if not loop.first %} || {% endif %}tagValue.equals("{{ discriminator }}"){% endfor %}) {
throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "{{ class_name }} variant '" + tagValue + "' is not available in this binding");
}
{% endif %}
throw new com.fasterxml.jackson.databind.JsonMappingException(
parser, "Unknown {{ class_name }} discriminator: " + tagValue);
}
};
{% endif %}
}
}