Skip to content

XmlMapper with FAIL_ON_UNKNOWN_PROPERTIES fails on whitespace-only element #892

Description

@retrodaredevil

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

Take this XML:

<Response>
	<Item name="example">
	</Item>
</Response>

If I want to deserialize that Item element into record Item(String name), I'm faced with this error:

Unrecognized property "" (class me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest$Item), not marked as ignorable (one known property: "name")
 at [No location information] (through reference chain: me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest$Response["Item"]->me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest$Item[""])
tools.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized property "" (class me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest$Item), not marked as ignorable (one known property: "name")
 at [No location information] (through reference chain: me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest$Response["Item"]->me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest$Item[""])
	at tools.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
	at tools.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:1378)
	at tools.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:2099)
	at tools.jackson.databind.deser.bean.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:2032)
	at tools.jackson.databind.deser.bean.BeanDeserializerBase.handleUnknownProperties(BeanDeserializerBase.java:1957)
	at tools.jackson.databind.deser.bean.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:922)
	at tools.jackson.databind.deser.bean.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1695)
	at tools.jackson.databind.deser.bean.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:629)
	at tools.jackson.databind.deser.bean.BeanDeserializer.deserialize(BeanDeserializer.java:200)
	at tools.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:568)
	at tools.jackson.databind.deser.bean.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:943)
	at tools.jackson.databind.deser.bean.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:775)
	at tools.jackson.databind.deser.bean.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1695)
	at tools.jackson.databind.deser.bean.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:629)
	at tools.jackson.databind.deser.bean.BeanDeserializer.deserialize(BeanDeserializer.java:200)
	at tools.jackson.dataformat.xml.deser.XmlDeserializationContext.readRootValue(XmlDeserializationContext.java:69)
	at tools.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2666)
	at tools.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1556)
	at me.retrodaredevil.randomjunkk.JacksonXmlWhitespaceOnlyContentTest.deserializesWhitespaceOnlyElementContent(JacksonXmlWhitespaceOnlyContentTest.java:27)

This is an issue for more complicated XML data, specifically data like this:

<Item name="thing">
    <AnotherElement name="thing"/>
</Item>

I run into this problem because Item typically has nested elements inside of it, but when it doesn't, the whitespace data within it is treated as a special blank string property.

Version Information

Jackson 3.2.1

Reproduction

import com.fasterxml.jackson.annotation.JsonProperty;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.dataformat.xml.XmlMapper;

import static org.junit.jupiter.api.Assertions.assertEquals;

class JacksonXmlWhitespaceOnlyContentTest {

	// This test fails because whitespace-only element content is exposed as an empty-named property.
	@Test
	void deserializesWhitespaceOnlyElementContent() {
		XmlMapper mapper = XmlMapper.builder()
				.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
				.build();
		String xml = """
				<Response>
					<Item name="example">
					</Item>
				</Response>
				""";

		Response response = mapper.readValue(xml, Response.class);

		assertEquals(new Item("example"), response.item());
	}

	record Response(
			@JsonProperty("Item") Item item
	) {
	}

	record Item(String name) {
	}
}

Expected behavior

FAIL_ON_UNKNOWN_PROPERTIES should only cause failures when there are actual properties that are unknown. I don't think this weird empty string property edge case should cause a failure here.

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    to-evaluateIssue that has been received but not yet evaluated

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions