Skip to content

Commit f4c7bb0

Browse files
committed
Implemented #156
1 parent 1a97b9d commit f4c7bb0

File tree

8 files changed

+85
-53
lines changed

8 files changed

+85
-53
lines changed

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Project: jackson-dataformat-xml
66

77
2.7.0 (not yet released)
88

9+
#156: Add `XmlMapper.setDefaultUseWrapper()` for convenience.
10+
911
2.6.2 (15-Sep-2015)
1012
2.6.1 (09-Aug-2015)
1113
2.6.0 (20-Jul-2015)

src/main/java/com/fasterxml/jackson/dataformat/xml/JacksonXmlAnnotationIntrospector.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.fasterxml.jackson.databind.PropertyName;
44
import com.fasterxml.jackson.databind.introspect.*;
55
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
6-
76
import com.fasterxml.jackson.dataformat.xml.annotation.*;
87

98
/**
@@ -25,7 +24,8 @@ public class JacksonXmlAnnotationIntrospector
2524
*/
2625
public final static boolean DEFAULT_USE_WRAPPER = true;
2726

28-
protected final boolean _cfgDefaultUseWrapper;
27+
// non-final from 2.7 on, to allow mapper to change
28+
protected boolean _cfgDefaultUseWrapper;
2929

3030
public JacksonXmlAnnotationIntrospector() {
3131
this(DEFAULT_USE_WRAPPER);
@@ -132,7 +132,12 @@ public Boolean isOutputAsCData(Annotated ann) {
132132
}
133133
return null;
134134
}
135-
135+
136+
@Override
137+
public void setDefaultUseWrapper(boolean b) {
138+
_cfgDefaultUseWrapper = b;
139+
}
140+
136141
/*
137142
/**********************************************************************
138143
/* Overrides for name, property detection

src/main/java/com/fasterxml/jackson/dataformat/xml/XmlAnnotationIntrospector.java

+24-4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public interface XmlAnnotationIntrospector
4242
*/
4343
public Boolean isOutputAsCData(Annotated ann);
4444

45+
/**
46+
* @since 2.7
47+
*/
48+
public void setDefaultUseWrapper(boolean b);
49+
4550
/*
4651
/**********************************************************************
4752
/* Replacement of 'AnnotationIntrospector.Pair' to use when combining
@@ -89,7 +94,7 @@ public static XmlAnnotationIntrospector.Pair instance(AnnotationIntrospector a1,
8994
public String findNamespace(Annotated ann)
9095
{
9196
String value = (_xmlPrimary == null) ? null : _xmlPrimary.findNamespace(ann);
92-
if (value == null && _xmlSecondary != null) {
97+
if ((value == null) && (_xmlSecondary != null)) {
9398
value = _xmlSecondary.findNamespace(ann);
9499
}
95100
return value;
@@ -99,7 +104,7 @@ public String findNamespace(Annotated ann)
99104
public Boolean isOutputAsAttribute(Annotated ann)
100105
{
101106
Boolean value = (_xmlPrimary == null) ? null : _xmlPrimary.isOutputAsAttribute(ann);
102-
if (value == null && _xmlSecondary != null) {
107+
if ((value == null) && (_xmlSecondary != null)) {
103108
value = _xmlSecondary.isOutputAsAttribute(ann);
104109
}
105110
return value;
@@ -109,7 +114,7 @@ public Boolean isOutputAsAttribute(Annotated ann)
109114
public Boolean isOutputAsText(Annotated ann)
110115
{
111116
Boolean value = (_xmlPrimary == null) ? null : _xmlPrimary.isOutputAsText(ann);
112-
if (value == null && _xmlSecondary != null) {
117+
if ((value == null) && (_xmlSecondary != null)) {
113118
value = _xmlSecondary.isOutputAsText(ann);
114119
}
115120
return value;
@@ -118,11 +123,21 @@ public Boolean isOutputAsText(Annotated ann)
118123
@Override
119124
public Boolean isOutputAsCData(Annotated ann) {
120125
Boolean value = (_xmlPrimary == null) ? null : _xmlPrimary.isOutputAsCData(ann);
121-
if (value == null && _xmlSecondary != null) {
126+
if ((value == null) && (_xmlSecondary != null)) {
122127
value = _xmlSecondary.isOutputAsCData(ann);
123128
}
124129
return value;
125130
}
131+
132+
@Override
133+
public void setDefaultUseWrapper(boolean b) {
134+
if (_xmlPrimary != null) {
135+
_xmlPrimary.setDefaultUseWrapper(b);
136+
}
137+
if (_xmlSecondary != null) {
138+
_xmlSecondary.setDefaultUseWrapper(b);
139+
}
140+
}
126141
}
127142

128143
/*
@@ -166,5 +181,10 @@ public Boolean isOutputAsCData(Annotated ann) {
166181
//There is no CData annotation in JAXB
167182
return null;
168183
}
184+
185+
@Override
186+
public void setDefaultUseWrapper(boolean b) {
187+
// not used with JAXB
188+
}
169189
}
170190
}

src/main/java/com/fasterxml/jackson/dataformat/xml/XmlMapper.java

+13-10
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ public XmlMapper(XmlFactory xmlFactory, JacksonXmlModule module)
8282
_serializationConfig = _serializationConfig.withDefaultPrettyPrinter(DEFAULT_XML_PRETTY_PRINTER);
8383
}
8484

85-
// @since 2.1
8685
@Override
8786
public XmlMapper copy()
8887
{
@@ -112,22 +111,26 @@ public Version version() {
112111
protected void setXMLTextElementName(String name) {
113112
((XmlFactory) _jsonFactory).setXMLTextElementName(name);
114113
}
114+
/**
115+
* Since 2.7
116+
*/
117+
public XmlMapper setDefaultUseWrapper(boolean state) {
118+
// ser and deser configs should usually have the same introspector, so:
119+
AnnotationIntrospector ai0 = getDeserializationConfig().getAnnotationIntrospector();
120+
for (AnnotationIntrospector ai : ai0.allIntrospectors()) {
121+
if (ai instanceof XmlAnnotationIntrospector) {
122+
((XmlAnnotationIntrospector) ai).setDefaultUseWrapper(state);
123+
}
124+
}
125+
return this;
126+
}
115127

116128
/*
117129
/**********************************************************
118130
/* Access to configuration settings
119131
/**********************************************************
120132
*/
121133

122-
/**
123-
* @deprecated Since 2.1, use {@link #getFactory} instead
124-
*/
125-
@Override
126-
@Deprecated
127-
public XmlFactory getJsonFactory() {
128-
return (XmlFactory) _jsonFactory;
129-
}
130-
131134
@Override
132135
public XmlFactory getFactory() {
133136
return (XmlFactory) _jsonFactory;

src/main/java/com/fasterxml/jackson/dataformat/xml/jaxb/XmlJaxbAnnotationIntrospector.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* implementation that
1515
* builds on {@link JaxbAnnotationIntrospector}.
1616
*<p>
17-
* NOTE: since version 2.4, it should NOT be necessary to use this class;
17+
* NOTE: since version 2.4, it may NOT be necessary to use this class;
1818
* instead, plain {@link JaxbAnnotationIntrospector} should fully work.
1919
* With previous versions some aspects were not fully working and this
2020
* class was necessary.
@@ -23,7 +23,7 @@ public class XmlJaxbAnnotationIntrospector
2323
extends JaxbAnnotationIntrospector
2424
implements XmlAnnotationIntrospector
2525
{
26-
private static final long serialVersionUID = 6477843393758275877L;
26+
private static final long serialVersionUID = 1L; // since 2.7
2727

2828
@Deprecated
2929
public XmlJaxbAnnotationIntrospector() {
@@ -40,19 +40,16 @@ public XmlJaxbAnnotationIntrospector(TypeFactory typeFactory) {
4040
/**********************************************************************
4141
*/
4242

43-
// Since 2.4.0, JaxbAnnotationIntrospector has implementation, so delegate
4443
@Override
4544
public String findNamespace(Annotated ann) {
4645
return super.findNamespace(ann);
4746
}
4847

49-
// Since 2.4.0, JaxbAnnotationIntrospector has implementation, so delegate
5048
@Override
5149
public Boolean isOutputAsAttribute(Annotated ann) {
5250
return super.isOutputAsAttribute(ann);
5351
}
5452

55-
// Since 2.4.0, JaxbAnnotationIntrospector has implementation, so delegate
5653
@Override
5754
public Boolean isOutputAsText(Annotated ann) {
5855
return super.isOutputAsText(ann);
@@ -64,6 +61,11 @@ public Boolean isOutputAsCData(Annotated ann) {
6461
return null;
6562
}
6663

64+
@Override
65+
public void setDefaultUseWrapper(boolean b) {
66+
// nothing to do with JAXB
67+
}
68+
6769
/*
6870
/**********************************************************************
6971
/* Helper methods

src/main/java/com/fasterxml/jackson/dataformat/xml/ser/XmlBeanSerializerBase.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,8 @@ protected void serializeFields(Object bean, JsonGenerator gen0, SerializerProvid
218218
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
219219
wrapAndThrow(provider, e, bean, name);
220220
} catch (StackOverflowError e) { // Bit tricky, can't do more calls as stack is full; so:
221-
JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)");
221+
JsonMappingException mapE = JsonMappingException.from(gen0,
222+
"Infinite recursion (StackOverflowError)");
222223
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
223224
mapE.prependPath(new JsonMappingException.Reference(bean, name));
224225
throw mapE;
@@ -294,7 +295,7 @@ protected void serializeFieldsFiltered(Object bean, JsonGenerator gen0,
294295
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
295296
wrapAndThrow(provider, e, bean, name);
296297
} catch (StackOverflowError e) {
297-
JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)", e);
298+
JsonMappingException mapE = JsonMappingException.from(gen0, "Infinite recursion (StackOverflowError)", e);
298299
String name = (i == props.length) ? "[anySetter]" : props[i].getName();
299300
mapE.prependPath(new JsonMappingException.Reference(bean, name));
300301
throw mapE;

src/main/java/com/fasterxml/jackson/dataformat/xml/ser/XmlSerializerProvider.java

+26-26
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ public DefaultSerializerProvider createInstance(SerializationConfig config,
6363

6464
@SuppressWarnings("resource")
6565
@Override
66-
public void serializeValue(JsonGenerator jgen, Object value)
66+
public void serializeValue(JsonGenerator gen, Object value)
6767
throws IOException
6868
{
6969
if (value == null) {
70-
_serializeXmlNull(jgen);
70+
_serializeXmlNull(gen);
7171
return;
7272
}
7373
final Class<?> cls = value.getClass();
7474
final boolean asArray;
75-
final ToXmlGenerator xgen = _asXmlGenerator(jgen);
75+
final ToXmlGenerator xgen = _asXmlGenerator(gen);
7676
if (xgen == null) { // called by convertValue()
7777
asArray = false;
7878
} else {
@@ -90,34 +90,34 @@ public void serializeValue(JsonGenerator jgen, Object value)
9090
// From super-class implementation
9191
final JsonSerializer<Object> ser = findTypedValueSerializer(cls, true, null);
9292
try {
93-
ser.serialize(value, jgen, this);
93+
ser.serialize(value, gen, this);
9494
} catch (IOException ioe) { // As per [JACKSON-99], pass IOException and subtypes as-is
9595
throw ioe;
9696
} catch (Exception e) { // but wrap RuntimeExceptions, to get path information
9797
String msg = e.getMessage();
9898
if (msg == null) {
9999
msg = "[no message for "+e.getClass().getName()+"]";
100100
}
101-
throw new JsonMappingException(msg, e);
101+
throw JsonMappingException.from(gen, msg, e);
102102
}
103103
// end of super-class implementation
104104

105105
if (asArray) {
106-
jgen.writeEndObject();
106+
gen.writeEndObject();
107107
}
108108
}
109109

110110
@SuppressWarnings("resource")
111111
@Override
112-
public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType)
112+
public void serializeValue(JsonGenerator gen, Object value, JavaType rootType)
113113
throws IOException
114114
{
115115
if (value == null) {
116-
_serializeXmlNull(jgen);
116+
_serializeXmlNull(gen);
117117
return;
118118
}
119119
final boolean asArray;
120-
final ToXmlGenerator xgen = _asXmlGenerator(jgen);
120+
final ToXmlGenerator xgen = _asXmlGenerator(gen);
121121
if (xgen == null) { // called by convertValue()
122122
asArray = false;
123123
} else {
@@ -135,35 +135,35 @@ public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType)
135135
final JsonSerializer<Object> ser = findTypedValueSerializer(rootType, true, null);
136136
// From super-class implementation
137137
try {
138-
ser.serialize(value, jgen, this);
138+
ser.serialize(value, gen, this);
139139
} catch (IOException ioe) { // no wrapping for IO (and derived)
140140
throw ioe;
141141
} catch (Exception e) { // but others do need to be, to get path etc
142142
String msg = e.getMessage();
143143
if (msg == null) {
144144
msg = "[no message for "+e.getClass().getName()+"]";
145145
}
146-
throw new JsonMappingException(msg, e);
146+
throw JsonMappingException.from(gen, msg, e);
147147
}
148148
// end of super-class implementation
149149

150150
if (asArray) {
151-
jgen.writeEndObject();
151+
gen.writeEndObject();
152152
}
153153
}
154154

155155
// @since 2.1
156156
@SuppressWarnings("resource")
157157
@Override
158-
public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType,
158+
public void serializeValue(JsonGenerator gen, Object value, JavaType rootType,
159159
JsonSerializer<Object> ser) throws IOException
160160
{
161161
if (value == null) {
162-
_serializeXmlNull(jgen);
162+
_serializeXmlNull(gen);
163163
return;
164164
}
165165
final boolean asArray;
166-
final ToXmlGenerator xgen = _asXmlGenerator(jgen);
166+
final ToXmlGenerator xgen = _asXmlGenerator(gen);
167167
if (xgen == null) { // called by convertValue()
168168
asArray = false;
169169
} else {
@@ -182,19 +182,19 @@ public void serializeValue(JsonGenerator jgen, Object value, JavaType rootType,
182182
}
183183
// From super-class implementation
184184
try {
185-
ser.serialize(value, jgen, this);
185+
ser.serialize(value, gen, this);
186186
} catch (IOException ioe) { // no wrapping for IO (and derived)
187187
throw ioe;
188188
} catch (Exception e) { // but others do need to be, to get path etc
189189
String msg = e.getMessage();
190190
if (msg == null) {
191191
msg = "[no message for "+e.getClass().getName()+"]";
192192
}
193-
throw new JsonMappingException(msg, e);
193+
throw JsonMappingException.from(gen, msg, e);
194194
}
195195
// end of super-class implementation
196196
if (asArray) {
197-
jgen.writeEndObject();
197+
gen.writeEndObject();
198198
}
199199
}
200200

@@ -252,18 +252,18 @@ protected QName _rootNameFromConfig()
252252
return new QName(ns, name.getSimpleName());
253253
}
254254

255-
protected ToXmlGenerator _asXmlGenerator(JsonGenerator jgen)
255+
protected ToXmlGenerator _asXmlGenerator(JsonGenerator gen)
256256
throws JsonMappingException
257257
{
258258
// [Issue#71]: When converting, we actually get TokenBuffer, which is fine
259-
if (!(jgen instanceof ToXmlGenerator)) {
259+
if (!(gen instanceof ToXmlGenerator)) {
260260
// but verify
261-
if (!(jgen instanceof TokenBuffer)) {
262-
throw new JsonMappingException("XmlMapper does not with generators of type other than ToXmlGenerator; got: "
263-
+jgen.getClass().getName());
264-
}
265-
return null;
261+
if (!(gen instanceof TokenBuffer)) {
262+
throw JsonMappingException.from(gen,
263+
"XmlMapper does not with generators of type other than ToXmlGenerator; got: "+gen.getClass().getName());
264+
}
265+
return null;
266266
}
267-
return (ToXmlGenerator) jgen;
267+
return (ToXmlGenerator) gen;
268268
}
269269
}

src/test/java/com/fasterxml/jackson/dataformat/xml/lists/NestedUnwrappedListsTest.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ static class VehicleActivity {
4040
public void setUp() throws Exception
4141
{
4242
super.setUp();
43-
JacksonXmlModule module = new JacksonXmlModule();
44-
module.setDefaultUseWrapper(false);
45-
_xmlMapper = new XmlMapper(module);
43+
_xmlMapper = new XmlMapper()
44+
.setDefaultUseWrapper(false);
4645
_xmlMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PascalCaseStrategy());
4746
_xmlMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
4847
}

0 commit comments

Comments
 (0)