question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Required attribute of `@JsonProperty` is ignored when deserializing from XML

See original GitHub issue

When JSON is parsed, there is a check on properties that are annotated with JsonProperty with attibute required to true. If the required property is missing, a MismatchedInputException with message “Missing required creator property” is thrown.

When XML is parsed, there is no check on required properties/element. If the required property/element is missing, there is no exception. Adding DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES doesn’t make any difference.

There is constructor is annotated with JsonCreator and with the required property annotated with JsonProperty.

It worked when jackson-dataformat-xml version 2.11.4 was used, it doesn’t work since version 2.12.0

Do I need to use another annotation for a required XML element?

Example class:

@JsonRootName(value = "bar")
public class Bar
{
    @JsonProperty(value = "foo", required = true)
    private int foo;

    public Bar()
    {}

    @JsonCreator
    public Bar(@JsonProperty(value = "foo", required = true) final int foo)
    {
        this.foo = foo;
    }

    public int getFoo()
    {
        return this.foo;
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(this.foo);
    }

    @Override
    public boolean equals(final Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (!(obj instanceof Bar))
        {
            return false;
        }
        final Bar other = (Bar) obj;
        return this.foo == other.foo;
    }

    @Override
    public String toString()
    {
        return "Bar: " + Objects.toString(this.foo);
    }
}

Example of unit test on JSON, this unit test throws an exception as expected, because property foo is missing.

    @Test(expected = JsonProcessingException.class)
    public void deserializeJson() throws Exception
    {
        final ObjectMapper jsonMapper = new ObjectMapper();

        final Bar expected = new Bar(123);
        final Bar actual = jsonMapper.readValue("{}", Bar.class); // missing property foo in JSON string
    }

Example of unit test on XML, this unit test does not throw an exception

  @Test(expected = JsonProcessingException.class)
   public void deserializeXml() throws Exception
   {
       final XmlMapper xmlMapper = new XmlMapper();
       xmlMapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, true);

       final Bar expected = new Bar(123);
       final Bar actual = xmlMapper.readValue("<bar></bar>", Bar.class); // missing element foo in XML string

       Assert.fail("Expected com.fasterxml.jackson.databind.exc.MismatchedInputException: Missing required creator property 'foo' (index 0)");
   }

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
johandeschutterGETcommented, Jul 4, 2022

The parsing of an empty XML element(1 tag, no start and end tag) is correct, if the feature FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL is enabled. The result is a NULL.

    @Test
    public void deserializeEmptyTag() throws Exception
    {
        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.configure(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL, true);
        final Bar actual = xmlMapper.readValue("<bar/>", Bar.class);
        Assert.assertNull(actual);
    }

The parsing of XML element with value empty string (start and end tag with empty string between), with feature FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL enabled, fails. The result is an object (Bar: 0) created by the default constructor, the required property foo is zero (= default value). There is no MismatchedInputException thrown for the missing foo property.

    @Test
    public void deserializeTagEmptyString() throws Exception
    {
        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.configure(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL, true);
        final Bar actual = xmlMapper.readValue("<bar></bar>", Bar.class);
        Assert.assertNull(actual); // java.lang.AssertionError: expected null, but was:<Bar: 0>
    }

The parsing of XML element with value empty string (start and end tag with empty string between) is correct, if the coercion configuration is defined for type Bar in order to process an empty string input as null.

    @Test
    public void deserializeTagEmptyStringCorrected() throws Exception
    {
        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.coercionConfigFor(Bar.class).setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull);
        final Bar actual = xmlMapper.readValue("<bar></bar>", Bar.class);
        Assert.assertNull(actual);
    }
0reactions
cowtowncodercommented, Sep 7, 2022

Ok, I was able to figure out a much simpler approach, essentially reverting some of the changes done in 2.12 for coercion root-element textual content. But without breaking what that change was initially added to fix.

So should work as expected in 2.14.0; hoping to release 2.14.0-rc1 within a week or so.

Read more comments on GitHub >

github_iconTop Results From Across the Web

jackson-dataformat-xml: Required attribute of JsonProperty ...
Jackson: jackson-dataformat-xml: Required attribute of JsonProperty annotation is ignored when deserializing from XML to Java.
Read more >
Jackson Ignore Properties on Marshalling - Baeldung
This tutorial will show how to ignore certain fields when serializing an object to JSON using Jackson 2.x.
Read more >
Controlling XML Serialization Using Attributes - Microsoft Learn
These attributes are similar. The XmlRootAttribute can be applied to only one class: the class that, when serialized, represents the XML ...
Read more >
Conditional Property Serialization - Json.NET
If the method returns true then the property will be serialized, if it returns false then the property will be skipped. Employee class...
Read more >
How to Ignore Properties Only For Serialization With Jackson
2. Basic Usage for @JsonIgnoreProperties ... Here, the name property is ignored and it is not in the JSON string. When we want...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found