FasterXML / jackson-dataformat-xml

Extension for Jackson JSON processor that adds support for serializing POJOs as XML (and deserializing from XML) as an alternative to JSON
Apache License 2.0
574 stars 222 forks source link

MismatchedInputException encountered while deserializing XML to an Enum type using a factory method #682

Open WannabeSoftwareEngineer opened 1 week ago

WannabeSoftwareEngineer commented 1 week ago

Hello, I'm trying to serialize an Enum type to XML, then read it back, but I get an input mismatch error related to JsonCreator.

Could someone provide insights into why deserialization fails?

Any help would is appreciated. Thank you.

Error

com.fasterxml.jackson.databind.exc.MismatchedInputException: Input mismatch reading Enum `com.xxx.yyy.Country`: properties-based `@JsonCreator` ([method com.xxx.yyy.Country#fromValue(java.lang.String)]) expects String Value, got Object value (`JsonToken.START_OBJECT`)

Test

@Test
void aTest() throws JsonProcessingException {
    XmlMapper xmlMapper = new XmlMapper();

    String s = xmlMapper.writeValueAsString(Country.ITALY);
    assertThat(s).isEqualTo("<Country>Italy</Country>");

    Country country = xmlMapper.readValue(s, Country.class);
    assertThat(country).isEqualTo(Country.ITALY); // fails with the error reported above
}

Country.java

public enum Country {
    ITALY("Italy"),
    NETHERLANDS("Netherlands");

    private String value;

    Country(String value) {
        this.value = value;
    }

    @JsonValue
    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return String.valueOf(value);
    }

    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
    public static Country fromValue(String value) {
        for (Country b : Country.values()) {
            if (b.value.equals(value)) {
                return b;
            }
        }
        throw new IllegalArgumentException("Unexpected value '" + value + "'");
    }
}

library: com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.17.1

original report submitted here: https://groups.google.com/g/jackson-user/c/xXgyb_uKbGg/m/fCcNz9WOCAAJ

pjfanning commented 1 week ago

Another issue with a similar JsonCreator annotation - https://github.com/FasterXML/jackson-databind/issues/4785

cowtowncoder commented 1 week ago

Probably not same root cause, but good to reference nonetheless. That one seems like invalid issue (but understandable; 2.18 changing behavior but in this case -- seems to me -- fixing it).

cowtowncoder commented 1 week ago

Note to self: jackson-databind EnumDeserializer has handling in

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
    {
         // ....
        if (p.hasToken(JsonToken.VALUE_STRING)) {
            return _fromString(p, ctxt, p.getText());
        }
         // ....
        // 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
        if (p.isExpectedStartObjectToken()) {
            return _fromString(p, ctxt,
                    ctxt.extractScalarFromObject(p, this, _valueClass));
        } 
    }

which handles special XML-ness aspects. But this is probably not handled for factory case, for some reason.