alef 0.110.4

Opinionated polyglot binding generator for Rust libraries
Documentation
/** 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 %}
  }
}