Skip to content

Commit 8d2e14c

Browse files
address feedback
1 parent 8989990 commit 8d2e14c

File tree

4 files changed

+118
-6
lines changed

4 files changed

+118
-6
lines changed

src/main/java/tools/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import tools.jackson.databind.cfg.MapperConfig;
99
import tools.jackson.databind.introspect.*;
1010
import tools.jackson.dataformat.xml.annotation.*;
11-
import tools.jackson.dataformat.xml.deser.FromXmlParser;
1211

1312
/**
1413
* Extension of {@link JacksonAnnotationIntrospector} that is needed to support
@@ -38,12 +37,19 @@ public class JacksonXmlAnnotationIntrospector
3837

3938
protected boolean _cfgDefaultUseWrapper;
4039

40+
protected final JacksonXmlAnnotationIntrospectorConfig _cfgIntrospectorConfig;
41+
4142
public JacksonXmlAnnotationIntrospector() {
4243
this(DEFAULT_USE_WRAPPER);
4344
}
4445

4546
public JacksonXmlAnnotationIntrospector(boolean defaultUseWrapper) {
47+
this(defaultUseWrapper, new JacksonXmlAnnotationIntrospectorConfig());
48+
}
49+
50+
public JacksonXmlAnnotationIntrospector(boolean defaultUseWrapper, JacksonXmlAnnotationIntrospectorConfig introspectorConfig) {
4651
_cfgDefaultUseWrapper = defaultUseWrapper;
52+
_cfgIntrospectorConfig = introspectorConfig;
4753
}
4854

4955
/*
@@ -85,7 +91,7 @@ public PropertyName findWrapperName(MapperConfig<?> config, Annotated ann)
8591
}
8692
return null;
8793
}
88-
94+
8995
@SuppressWarnings("deprecation")
9096
@Override
9197
public PropertyName findRootName(MapperConfig<?> config, AnnotatedClass ac)
@@ -94,7 +100,7 @@ public PropertyName findRootName(MapperConfig<?> config, AnnotatedClass ac)
94100
if (root != null) {
95101
String local = root.localName();
96102
String ns = root.namespace();
97-
103+
98104
if (local.length() == 0 && ns.length() == 0) {
99105
return PropertyName.USE_DEFAULT;
100106
}
@@ -209,8 +215,11 @@ public PropertyName findNameForDeserialization(MapperConfig<?> config, Annotated
209215
PropertyName pn = PropertyName.merge(_findXmlName(a),
210216
super.findNameForDeserialization(config, a));
211217
if (pn == null) {
212-
if(_hasAnnotation(a, JacksonXmlText.class)){
213-
return PropertyName.construct(FromXmlParser.DEFAULT_TEXT_PROPERTY);
218+
JacksonXmlText jacksonXmlTextAnnotation = _findAnnotation(a, JacksonXmlText.class);
219+
220+
if (jacksonXmlTextAnnotation != null && jacksonXmlTextAnnotation.value() &&
221+
!_cfgIntrospectorConfig.inferXmlTextPropertyName()) {
222+
return _cfgIntrospectorConfig.xmlTextPropertyName();
214223
}
215224

216225
if (_hasOneOf(a, ANNOTATIONS_TO_INFER_XML_PROP)) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package tools.jackson.dataformat.xml;
2+
3+
import tools.jackson.databind.PropertyName;
4+
import tools.jackson.dataformat.xml.deser.FromXmlParser;
5+
6+
import java.io.Serializable;
7+
8+
public record JacksonXmlAnnotationIntrospectorConfig(
9+
boolean inferXmlTextPropertyName,
10+
PropertyName xmlTextPropertyName //Only honored if inferXmlTextPropertyName is false
11+
) implements Serializable {
12+
13+
/**
14+
* Constructs a JacksonXmlAnnotationIntrospectorConfig with the default configuration
15+
* Does not infer the XmlTextPropertyName by default and uses {@link FromXmlParser#DEFAULT_TEXT_PROPERTY} for the {@link PropertyName}.
16+
*/
17+
public JacksonXmlAnnotationIntrospectorConfig() {
18+
this(false, PropertyName.construct(FromXmlParser.DEFAULT_TEXT_PROPERTY));
19+
}
20+
21+
public JacksonXmlAnnotationIntrospectorConfig withInferXmlTextPropertyName(boolean inferXmlTextPropertyName) {
22+
return new JacksonXmlAnnotationIntrospectorConfig(inferXmlTextPropertyName, this.xmlTextPropertyName);
23+
}
24+
25+
public JacksonXmlAnnotationIntrospectorConfig withXmlTextPropertyName(PropertyName xmlTextPropertyName) {
26+
return new JacksonXmlAnnotationIntrospectorConfig(this.inferXmlTextPropertyName, xmlTextPropertyName);
27+
}
28+
}

src/main/java/tools/jackson/dataformat/xml/deser/FromXmlParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public class FromXmlParser
3636
{
3737
/**
3838
* The default name placeholder for XML text segments is &lt;xml:text&gt;
39-
* @since 3.0.0 Is now &lt;xml:text&gt; - was empty String ("") before.
39+
* @since 3.0 Is now &lt;xml:text&gt; - was empty String ("") before.
4040
*/
4141
public final static String DEFAULT_TEXT_PROPERTY = "<xml:text>";
4242

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package tools.jackson.dataformat.xml.deser;
2+
3+
import org.junit.jupiter.api.Test;
4+
import tools.jackson.databind.DatabindException;
5+
import tools.jackson.databind.PropertyName;
6+
import tools.jackson.dataformat.xml.JacksonXmlAnnotationIntrospector;
7+
import tools.jackson.dataformat.xml.JacksonXmlAnnotationIntrospectorConfig;
8+
import tools.jackson.dataformat.xml.XmlMapper;
9+
import tools.jackson.dataformat.xml.XmlTestUtil;
10+
import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty;
11+
import tools.jackson.dataformat.xml.annotation.JacksonXmlText;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.junit.jupiter.api.Assertions.assertThrows;
15+
import static org.junit.jupiter.api.Assertions.assertTrue;
16+
17+
public class DifferentDeserializationPropertyNameTest extends XmlTestUtil {
18+
19+
static class TestBean {
20+
21+
@JacksonXmlProperty(localName = "wrong")
22+
String wrong;
23+
24+
@JacksonXmlText
25+
String name;
26+
27+
28+
}
29+
30+
/*
31+
/**********************************************************************
32+
/* Test methods
33+
/**********************************************************************
34+
*/
35+
36+
@Test
37+
public void testWithExplicitProperty() {
38+
final XmlMapper mapper = XmlMapper.builder()
39+
.annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("name"))))
40+
.build();
41+
42+
String xmlInput = "<testBean>ABC123</testBean>";
43+
44+
TestBean testBean = mapper.readValue(xmlInput, TestBean.class);
45+
46+
assertEquals("ABC123", testBean.name);
47+
}
48+
49+
@Test
50+
public void testWithInferName() {
51+
final XmlMapper mapper = XmlMapper.builder()
52+
.annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(true, null)))
53+
.build();
54+
55+
String xmlInput = "<testBean>DEF</testBean>";
56+
57+
TestBean testBean = mapper.readValue(xmlInput, TestBean.class);
58+
59+
assertEquals("DEF", testBean.name);
60+
}
61+
62+
@Test
63+
public void testWithDuplicateExplicitProperty() {
64+
final XmlMapper mapper = XmlMapper.builder()
65+
.annotationIntrospector(new JacksonXmlAnnotationIntrospector(false, new JacksonXmlAnnotationIntrospectorConfig(false, new PropertyName("wrong"))))
66+
.build();
67+
68+
String xmlInput = "<testBean>DEF</testBean>";
69+
70+
Exception result = assertThrows(DatabindException.class, () -> mapper.readValue(xmlInput, TestBean.class));
71+
72+
assertTrue(result.getMessage().contains("Multiple fields representing property \"wrong\""));
73+
}
74+
75+
}

0 commit comments

Comments
 (0)