From c53bc2732577ddb48684711ed1271543f78db2a6 Mon Sep 17 00:00:00 2001 From: duoduobingbing <50800372+duoduobingbing@users.noreply.github.com> Date: Mon, 28 Apr 2025 20:57:53 +0200 Subject: [PATCH 1/4] change default property name for xml text from empty string to `` --- .../xml/JacksonXmlAnnotationIntrospector.java | 5 +++++ .../java/tools/jackson/dataformat/xml/XmlMapper.java | 2 +- .../jackson/dataformat/xml/deser/FromXmlParser.java | 8 ++++---- .../xml/deser/XmlDeserializationContext.java | 2 +- .../dataformat/xml/deser/MapDeserializationTest.java | 2 +- .../dataformat/xml/deser/UntypedObjectDeserTest.java | 2 +- .../dataformat/xml/node/JsonNodeBasicDeserTest.java | 3 ++- .../xml/node/JsonNodeMixedContent403Test.java | 11 ++++++----- .../dataformat/xml/stream/XmlParser442Test.java | 2 +- .../jackson/dataformat/xml/stream/XmlParserTest.java | 8 ++++---- .../xml/tofix/XmlTextViaCreator306Test.java | 1 - .../xml/tofix/records/XmlRecordDeser734Test.java | 1 - 12 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java b/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java index e8607921..1bf70fd6 100644 --- a/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java +++ b/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java @@ -8,6 +8,7 @@ import tools.jackson.databind.cfg.MapperConfig; import tools.jackson.databind.introspect.*; import tools.jackson.dataformat.xml.annotation.*; +import tools.jackson.dataformat.xml.deser.FromXmlParser; /** * Extension of {@link JacksonAnnotationIntrospector} that is needed to support @@ -208,6 +209,10 @@ public PropertyName findNameForDeserialization(MapperConfig config, Annotated PropertyName pn = PropertyName.merge(_findXmlName(a), super.findNameForDeserialization(config, a)); if (pn == null) { + if(_hasAnnotation(a, JacksonXmlText.class)){ + return PropertyName.construct(FromXmlParser.DEFAULT_TEXT_PROPERTY); + } + if (_hasOneOf(a, ANNOTATIONS_TO_INFER_XML_PROP)) { return PropertyName.USE_DEFAULT; } diff --git a/src/main/java/tools/jackson/dataformat/xml/XmlMapper.java b/src/main/java/tools/jackson/dataformat/xml/XmlMapper.java index 01d0c052..b6cbe15d 100644 --- a/src/main/java/tools/jackson/dataformat/xml/XmlMapper.java +++ b/src/main/java/tools/jackson/dataformat/xml/XmlMapper.java @@ -67,7 +67,7 @@ public Builder(XmlFactory f) { // String into `null` (where it otherwise is an error) is very useful. enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); _defaultUseWrapper = JacksonXmlAnnotationIntrospector.DEFAULT_USE_WRAPPER; - _nameForTextElement = FromXmlParser.DEFAULT_UNNAMED_TEXT_PROPERTY; + _nameForTextElement = FromXmlParser.DEFAULT_TEXT_PROPERTY; // as well as AnnotationIntrospector: note, however, that "use wrapper" may well // change later on diff --git a/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java b/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java index 9d31bf12..c07815a9 100644 --- a/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java +++ b/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java @@ -35,10 +35,10 @@ public class FromXmlParser implements ElementWrappable { /** - * The default name placeholder for XML text segments is empty - * String (""). + * The default name placeholder for XML text segments is <xml:text> + * @since 3.0.0 Is now <xml:text> - was empty String ("") before. */ - public final static String DEFAULT_UNNAMED_TEXT_PROPERTY = ""; + public final static String DEFAULT_TEXT_PROPERTY = ""; /** * XML format has some peculiarities, indicated via capability @@ -61,7 +61,7 @@ public class FromXmlParser * may be changed for inter-operability reasons: JAXB, for example, uses * "value" as name. */ - protected String _cfgNameForTextElement = DEFAULT_UNNAMED_TEXT_PROPERTY; + protected String _cfgNameForTextElement = DEFAULT_TEXT_PROPERTY; /* /********************************************************************** diff --git a/src/main/java/tools/jackson/dataformat/xml/deser/XmlDeserializationContext.java b/src/main/java/tools/jackson/dataformat/xml/deser/XmlDeserializationContext.java index 46be9cf8..26957a2e 100644 --- a/src/main/java/tools/jackson/dataformat/xml/deser/XmlDeserializationContext.java +++ b/src/main/java/tools/jackson/dataformat/xml/deser/XmlDeserializationContext.java @@ -68,7 +68,7 @@ public String extractScalarFromObject(JsonParser p, ValueDeserializer deser, final String propName = p.currentName(); JsonToken t = p.nextToken(); if (t == JsonToken.VALUE_STRING) { - if (propName.equals("")) { + if (FromXmlParser.DEFAULT_TEXT_PROPERTY.equals(propName)) { text = p.getString(); } } else { diff --git a/src/test/java/tools/jackson/dataformat/xml/deser/MapDeserializationTest.java b/src/test/java/tools/jackson/dataformat/xml/deser/MapDeserializationTest.java index 55bbf4b5..ae622e3a 100644 --- a/src/test/java/tools/jackson/dataformat/xml/deser/MapDeserializationTest.java +++ b/src/test/java/tools/jackson/dataformat/xml/deser/MapDeserializationTest.java @@ -41,7 +41,7 @@ public void testMapWithAttr() throws Exception assertEquals(1, map.size()); Map inner = new LinkedHashMap<>(); inner.put("lang", "en"); - inner.put("", "John Smith"); + inner.put(FromXmlParser.DEFAULT_TEXT_PROPERTY, "John Smith"); assertEquals(Collections.singletonMap("person", inner), map); } } diff --git a/src/test/java/tools/jackson/dataformat/xml/deser/UntypedObjectDeserTest.java b/src/test/java/tools/jackson/dataformat/xml/deser/UntypedObjectDeserTest.java index af705490..931293ba 100644 --- a/src/test/java/tools/jackson/dataformat/xml/deser/UntypedObjectDeserTest.java +++ b/src/test/java/tools/jackson/dataformat/xml/deser/UntypedObjectDeserTest.java @@ -77,7 +77,7 @@ public void testMixedContent() throws Exception final String XML = "first123secondabclast"; final JsonNode fromXml = XML_MAPPER.valueToTree(XML_MAPPER.readValue(XML, Object.class)); final ObjectNode exp = XML_MAPPER.createObjectNode(); - exp.putArray("") + exp.putArray(FromXmlParser.DEFAULT_TEXT_PROPERTY) .add("first") .add("second") .add("last"); diff --git a/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeBasicDeserTest.java b/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeBasicDeserTest.java index b774f9e2..66024792 100644 --- a/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeBasicDeserTest.java +++ b/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeBasicDeserTest.java @@ -7,6 +7,7 @@ import tools.jackson.databind.node.JsonNodeType; import tools.jackson.databind.node.ObjectNode; import tools.jackson.dataformat.xml.XmlTestUtil; +import tools.jackson.dataformat.xml.deser.FromXmlParser; import static org.junit.jupiter.api.Assertions.*; @@ -43,7 +44,7 @@ public void testMixedContent() throws Exception { JsonNode fromXml = XML_MAPPER.readTree("first123secondabclast"); final ObjectNode exp = XML_MAPPER.createObjectNode(); - exp.putArray("") + exp.putArray(FromXmlParser.DEFAULT_TEXT_PROPERTY) .add("first") .add("second") .add("last"); diff --git a/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeMixedContent403Test.java b/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeMixedContent403Test.java index f7355b30..96cbe73c 100644 --- a/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeMixedContent403Test.java +++ b/src/test/java/tools/jackson/dataformat/xml/node/JsonNodeMixedContent403Test.java @@ -6,6 +6,7 @@ import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import tools.jackson.dataformat.xml.XmlTestUtil; +import tools.jackson.dataformat.xml.deser.FromXmlParser; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -19,7 +20,7 @@ public class JsonNodeMixedContent403Test extends XmlTestUtil public void testMixedContentBefore() throws Exception { // First, before elements: - assertEquals(JSON_MAPPER.readTree(a2q("{'':'before','a':'1','b':'2'}")), + assertEquals(JSON_MAPPER.readTree(a2q(String.format("{'%s':'before','a':'1','b':'2'}", FromXmlParser.DEFAULT_TEXT_PROPERTY))), XML_MAPPER.readTree("before12")); } @@ -27,7 +28,7 @@ public void testMixedContentBefore() throws Exception public void testMixedContentBetween() throws Exception { // Second, between - assertEquals(JSON_MAPPER.readTree(a2q("{'a':'1','':'between','b':'2'}")), + assertEquals(JSON_MAPPER.readTree(a2q(String.format("{'a':'1','%s':'between','b':'2'}", FromXmlParser.DEFAULT_TEXT_PROPERTY))), XML_MAPPER.readTree("1between2")); } @@ -35,7 +36,7 @@ public void testMixedContentBetween() throws Exception public void testMixedContentAfter() throws Exception { // and then after - assertEquals(JSON_MAPPER.readTree(a2q("{'a':'1','b':'2','':'after'}")), + assertEquals(JSON_MAPPER.readTree(a2q(String.format("{'a':'1','b':'2','%s':'after'}", FromXmlParser.DEFAULT_TEXT_PROPERTY))), XML_MAPPER.readTree("12after")); } @@ -44,7 +45,7 @@ public void testMultipleMixedContent() throws Exception { // and then after assertEquals(JSON_MAPPER.readTree( - a2q("{'':['first','second','third'],'a':'1','b':'2'}")), + a2q(String.format("{'%s':['first','second','third'],'a':'1','b':'2'}", FromXmlParser.DEFAULT_TEXT_PROPERTY))), XML_MAPPER.readTree("first1second2third")); } @@ -57,7 +58,7 @@ public void testMixed226() throws Exception +" mixed2\n" +""; JsonNode fromJson = JSON_MAPPER.readTree( - a2q("{'a':{'':['mixed1 ',' mixed2'],'b':'leaf'}}")); + a2q(String.format("{'a':{'%s':['mixed1 ',' mixed2'],'b':'leaf'}}", FromXmlParser.DEFAULT_TEXT_PROPERTY))); assertEquals(fromJson, XML_MAPPER.readTree(XML)); } } diff --git a/src/test/java/tools/jackson/dataformat/xml/stream/XmlParser442Test.java b/src/test/java/tools/jackson/dataformat/xml/stream/XmlParser442Test.java index 105a20e0..131d9702 100644 --- a/src/test/java/tools/jackson/dataformat/xml/stream/XmlParser442Test.java +++ b/src/test/java/tools/jackson/dataformat/xml/stream/XmlParser442Test.java @@ -44,7 +44,7 @@ public void testMixedContentBeforeElement442() throws Exception // Here's what we are missing: assertToken(JsonToken.START_OBJECT, xp.nextToken()); assertToken(JsonToken.PROPERTY_NAME, xp.nextToken()); - assertEquals("", xp.currentName()); + assertEquals(FromXmlParser.DEFAULT_TEXT_PROPERTY, xp.currentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertEquals("text", xp.getString().trim()); diff --git a/src/test/java/tools/jackson/dataformat/xml/stream/XmlParserTest.java b/src/test/java/tools/jackson/dataformat/xml/stream/XmlParserTest.java index 280cf553..519f6e41 100644 --- a/src/test/java/tools/jackson/dataformat/xml/stream/XmlParserTest.java +++ b/src/test/java/tools/jackson/dataformat/xml/stream/XmlParserTest.java @@ -99,7 +99,7 @@ public void testRootScalar() throws Exception try (JsonParser p = _xmlMapper.createParser(XML)) { assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.PROPERTY_NAME, p.nextToken()); - assertEquals("", p.currentName()); + assertEquals(FromXmlParser.DEFAULT_TEXT_PROPERTY, p.currentName()); assertToken(JsonToken.VALUE_STRING, p.nextToken()); assertEquals("value", p.getString()); assertToken(JsonToken.END_OBJECT, p.nextToken()); @@ -118,7 +118,7 @@ public void testRootMixed() throws Exception assertToken(JsonToken.START_OBJECT, p.nextToken()); assertToken(JsonToken.PROPERTY_NAME, p.nextToken()); - assertEquals("", p.currentName()); + assertEquals(FromXmlParser.DEFAULT_TEXT_PROPERTY, p.currentName()); assertToken(JsonToken.VALUE_STRING, p.nextToken()); assertEquals("value", p.getString()); @@ -343,7 +343,7 @@ public void testXmlAttributes() throws Exception @Test public void testMixedContent() throws Exception { - String exp = a2q("{'':'first','a':'123','':'second','b':'456','':'last'}"); + String exp = a2q(String.format("{'%1$s':'first','a':'123','%1$s':'second','b':'456','%1$s':'last'}", FromXmlParser.DEFAULT_TEXT_PROPERTY)); String result = _readXmlWriteJson("first123second456last"); //System.err.println("result = \n"+result); @@ -373,7 +373,7 @@ public void testInferredNumbers() throws Exception assertEquals(42, xp.getIntValue()); assertToken(JsonToken.PROPERTY_NAME, xp.nextToken()); // implicit for text - assertEquals("", xp.currentName()); + assertEquals(FromXmlParser.DEFAULT_TEXT_PROPERTY, xp.currentName()); assertToken(JsonToken.VALUE_STRING, xp.nextToken()); assertTrue(xp.isExpectedNumberIntToken()); diff --git a/src/test/java/tools/jackson/dataformat/xml/tofix/XmlTextViaCreator306Test.java b/src/test/java/tools/jackson/dataformat/xml/tofix/XmlTextViaCreator306Test.java index a54b2341..9e68718a 100644 --- a/src/test/java/tools/jackson/dataformat/xml/tofix/XmlTextViaCreator306Test.java +++ b/src/test/java/tools/jackson/dataformat/xml/tofix/XmlTextViaCreator306Test.java @@ -116,7 +116,6 @@ public void testIssue306NoCtor() throws Exception } // [dataformat-xml#423] - @JacksonTestFailureExpected @Test public void testXmlTextViaCtor423() throws Exception { diff --git a/src/test/java/tools/jackson/dataformat/xml/tofix/records/XmlRecordDeser734Test.java b/src/test/java/tools/jackson/dataformat/xml/tofix/records/XmlRecordDeser734Test.java index d303abcb..b9da7dd8 100644 --- a/src/test/java/tools/jackson/dataformat/xml/tofix/records/XmlRecordDeser734Test.java +++ b/src/test/java/tools/jackson/dataformat/xml/tofix/records/XmlRecordDeser734Test.java @@ -18,7 +18,6 @@ record Amount(@JacksonXmlText String value, private final String XML = a2q("1"); - @JacksonTestFailureExpected @Test public void testDeser() throws Exception { XmlMapper mapper = new XmlMapper(); From 8d2e14c189374f333ac5cdc7b7a49bbe2dc72391 Mon Sep 17 00:00:00 2001 From: duoduobingbing <50800372+duoduobingbing@users.noreply.github.com> Date: Fri, 2 May 2025 14:38:09 +0200 Subject: [PATCH 2/4] address feedback --- .../xml/JacksonXmlAnnotationIntrospector.java | 19 +++-- ...acksonXmlAnnotationIntrospectorConfig.java | 28 +++++++ .../dataformat/xml/deser/FromXmlParser.java | 2 +- ...ferentDeserializationPropertyNameTest.java | 75 +++++++++++++++++++ 4 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospectorConfig.java create mode 100644 src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java diff --git a/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java b/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java index 1bf70fd6..2ce0e5ba 100644 --- a/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java +++ b/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java @@ -8,7 +8,6 @@ import tools.jackson.databind.cfg.MapperConfig; import tools.jackson.databind.introspect.*; import tools.jackson.dataformat.xml.annotation.*; -import tools.jackson.dataformat.xml.deser.FromXmlParser; /** * Extension of {@link JacksonAnnotationIntrospector} that is needed to support @@ -38,12 +37,19 @@ public class JacksonXmlAnnotationIntrospector protected boolean _cfgDefaultUseWrapper; + protected final JacksonXmlAnnotationIntrospectorConfig _cfgIntrospectorConfig; + public JacksonXmlAnnotationIntrospector() { this(DEFAULT_USE_WRAPPER); } public JacksonXmlAnnotationIntrospector(boolean defaultUseWrapper) { + this(defaultUseWrapper, new JacksonXmlAnnotationIntrospectorConfig()); + } + + public JacksonXmlAnnotationIntrospector(boolean defaultUseWrapper, JacksonXmlAnnotationIntrospectorConfig introspectorConfig) { _cfgDefaultUseWrapper = defaultUseWrapper; + _cfgIntrospectorConfig = introspectorConfig; } /* @@ -85,7 +91,7 @@ public PropertyName findWrapperName(MapperConfig config, Annotated ann) } return null; } - + @SuppressWarnings("deprecation") @Override public PropertyName findRootName(MapperConfig config, AnnotatedClass ac) @@ -94,7 +100,7 @@ public PropertyName findRootName(MapperConfig config, AnnotatedClass ac) if (root != null) { String local = root.localName(); String ns = root.namespace(); - + if (local.length() == 0 && ns.length() == 0) { return PropertyName.USE_DEFAULT; } @@ -209,8 +215,11 @@ public PropertyName findNameForDeserialization(MapperConfig config, Annotated PropertyName pn = PropertyName.merge(_findXmlName(a), super.findNameForDeserialization(config, a)); if (pn == null) { - if(_hasAnnotation(a, JacksonXmlText.class)){ - return PropertyName.construct(FromXmlParser.DEFAULT_TEXT_PROPERTY); + JacksonXmlText jacksonXmlTextAnnotation = _findAnnotation(a, JacksonXmlText.class); + + if (jacksonXmlTextAnnotation != null && jacksonXmlTextAnnotation.value() && + !_cfgIntrospectorConfig.inferXmlTextPropertyName()) { + return _cfgIntrospectorConfig.xmlTextPropertyName(); } if (_hasOneOf(a, ANNOTATIONS_TO_INFER_XML_PROP)) { diff --git a/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospectorConfig.java b/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospectorConfig.java new file mode 100644 index 00000000..c0fa74d3 --- /dev/null +++ b/src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospectorConfig.java @@ -0,0 +1,28 @@ +package tools.jackson.dataformat.xml; + +import tools.jackson.databind.PropertyName; +import tools.jackson.dataformat.xml.deser.FromXmlParser; + +import java.io.Serializable; + +public record JacksonXmlAnnotationIntrospectorConfig( + boolean inferXmlTextPropertyName, + PropertyName xmlTextPropertyName //Only honored if inferXmlTextPropertyName is false +) implements Serializable { + + /** + * Constructs a JacksonXmlAnnotationIntrospectorConfig with the default configuration + * Does not infer the XmlTextPropertyName by default and uses {@link FromXmlParser#DEFAULT_TEXT_PROPERTY} for the {@link PropertyName}. + */ + public JacksonXmlAnnotationIntrospectorConfig() { + this(false, PropertyName.construct(FromXmlParser.DEFAULT_TEXT_PROPERTY)); + } + + public JacksonXmlAnnotationIntrospectorConfig withInferXmlTextPropertyName(boolean inferXmlTextPropertyName) { + return new JacksonXmlAnnotationIntrospectorConfig(inferXmlTextPropertyName, this.xmlTextPropertyName); + } + + public JacksonXmlAnnotationIntrospectorConfig withXmlTextPropertyName(PropertyName xmlTextPropertyName) { + return new JacksonXmlAnnotationIntrospectorConfig(this.inferXmlTextPropertyName, xmlTextPropertyName); + } +} diff --git a/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java b/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java index c07815a9..153c002a 100644 --- a/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java +++ b/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java @@ -36,7 +36,7 @@ public class FromXmlParser { /** * The default name placeholder for XML text segments is <xml:text> - * @since 3.0.0 Is now <xml:text> - was empty String ("") before. + * @since 3.0 Is now <xml:text> - was empty String ("") before. */ public final static String DEFAULT_TEXT_PROPERTY = ""; diff --git a/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java b/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java new file mode 100644 index 00000000..a5bc31a9 --- /dev/null +++ b/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java @@ -0,0 +1,75 @@ +package tools.jackson.dataformat.xml.deser; + +import org.junit.jupiter.api.Test; +import tools.jackson.databind.DatabindException; +import tools.jackson.databind.PropertyName; +import tools.jackson.dataformat.xml.JacksonXmlAnnotationIntrospector; +import tools.jackson.dataformat.xml.JacksonXmlAnnotationIntrospectorConfig; +import tools.jackson.dataformat.xml.XmlMapper; +import tools.jackson.dataformat.xml.XmlTestUtil; +import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty; +import tools.jackson.dataformat.xml.annotation.JacksonXmlText; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class DifferentDeserializationPropertyNameTest extends XmlTestUtil { + + static class TestBean { + + @JacksonXmlProperty(localName = "wrong") + String wrong; + + @JacksonXmlText + String name; + + + } + + /* + /********************************************************************** + /* Test methods + /********************************************************************** + */ + + @Test + public void testWithExplicitProperty() { + final XmlMapper mapper = XmlMapper.builder() + .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("name")))) + .build(); + + String xmlInput = "ABC123"; + + TestBean testBean = mapper.readValue(xmlInput, TestBean.class); + + assertEquals("ABC123", testBean.name); + } + + @Test + public void testWithInferName() { + final XmlMapper mapper = XmlMapper.builder() + .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(true, null))) + .build(); + + String xmlInput = "DEF"; + + TestBean testBean = mapper.readValue(xmlInput, TestBean.class); + + assertEquals("DEF", testBean.name); + } + + @Test + public void testWithDuplicateExplicitProperty() { + final XmlMapper mapper = XmlMapper.builder() + .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("wrong")))) + .build(); + + String xmlInput = "DEF"; + + Exception result = assertThrows(DatabindException.class, () -> mapper.readValue(xmlInput, TestBean.class)); + + assertTrue(result.getMessage().contains("Multiple fields representing property \"wrong\"")); + } + +} From 6ed7c4ba84d3eca9cea2074eddf2d958bfba5db7 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 12 May 2025 18:29:58 -0700 Subject: [PATCH 3/4] Minor rephrasing of Javadocs --- .../tools/jackson/dataformat/xml/deser/FromXmlParser.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java b/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java index 153c002a..bbbd9320 100644 --- a/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java +++ b/src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java @@ -35,8 +35,12 @@ public class FromXmlParser implements ElementWrappable { /** - * The default name placeholder for XML text segments is <xml:text> - * @since 3.0 Is now <xml:text> - was empty String ("") before. + * The default name placeholder for XML text segments: used because Token stream + * requires all values inside "Objects" to have names associated. + * For Jackson 3.x this is {@code }; in 2.x matching constant was defined + * as empty String ({@code ""}). + * + * @since 3.0 Constant was renamed: was {@code DEFAULT_UNNAMED_TEXT_PROPERTY} in 2.x */ public final static String DEFAULT_TEXT_PROPERTY = ""; From ff896b62c88b2313be52ad605e2abd38b2c8a8af Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 12 May 2025 18:31:53 -0700 Subject: [PATCH 4/4] ws clean up --- ...ifferentDeserializationPropertyNameTest.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java b/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java index a5bc31a9..b5172a97 100644 --- a/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java +++ b/src/test/java/tools/jackson/dataformat/xml/deser/DifferentDeserializationPropertyNameTest.java @@ -14,17 +14,14 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -public class DifferentDeserializationPropertyNameTest extends XmlTestUtil { - +public class DifferentDeserializationPropertyNameTest extends XmlTestUtil +{ static class TestBean { - @JacksonXmlProperty(localName = "wrong") String wrong; @JacksonXmlText String name; - - } /* @@ -36,7 +33,8 @@ static class TestBean { @Test public void testWithExplicitProperty() { final XmlMapper mapper = XmlMapper.builder() - .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("name")))) + .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, + new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("name")))) .build(); String xmlInput = "ABC123"; @@ -49,7 +47,8 @@ public void testWithExplicitProperty() { @Test public void testWithInferName() { final XmlMapper mapper = XmlMapper.builder() - .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(true, null))) + .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, + new JacksonXmlAnnotationIntrospectorConfig(true, null))) .build(); String xmlInput = "DEF"; @@ -62,7 +61,8 @@ public void testWithInferName() { @Test public void testWithDuplicateExplicitProperty() { final XmlMapper mapper = XmlMapper.builder() - .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("wrong")))) + .annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, + new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("wrong")))) .build(); String xmlInput = "DEF"; @@ -71,5 +71,4 @@ public void testWithDuplicateExplicitProperty() { assertTrue(result.getMessage().contains("Multiple fields representing property \"wrong\"")); } - }