Add defaultUseWrapper support to Jackson builder
Issue: SPR-13975
This commit is contained in:
parent
ffbf264976
commit
7b861c9a8a
|
@ -47,6 +47,8 @@ import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
|
|||
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.ser.FilterProvider;
|
||||
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlFactory;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
@ -127,6 +129,8 @@ public class Jackson2ObjectMapperBuilder {
|
|||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private Boolean defaultUseWrapper;
|
||||
|
||||
|
||||
/**
|
||||
* If set to {@code true}, an {@link XmlMapper} will be created using its
|
||||
|
@ -392,6 +396,16 @@ public class Jackson2ObjectMapperBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define if a wrapper will be used for indexed (List, array) properties or not by
|
||||
* default (only applies to {@link XmlMapper}).
|
||||
* @since 4.3
|
||||
*/
|
||||
public Jackson2ObjectMapperBuilder defaultUseWrapper(boolean defaultUseWrapper) {
|
||||
this.defaultUseWrapper = defaultUseWrapper;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify features to enable.
|
||||
* @see com.fasterxml.jackson.core.JsonParser.Feature
|
||||
|
@ -547,7 +561,8 @@ public class Jackson2ObjectMapperBuilder {
|
|||
public <T extends ObjectMapper> T build() {
|
||||
ObjectMapper mapper;
|
||||
if (this.createXmlMapper) {
|
||||
mapper = new XmlObjectMapperInitializer().create();
|
||||
mapper = (this.defaultUseWrapper == null ? new XmlObjectMapperInitializer().create()
|
||||
: new XmlObjectMapperInitializer().create(this.defaultUseWrapper));
|
||||
}
|
||||
else {
|
||||
mapper = new ObjectMapper();
|
||||
|
@ -757,11 +772,21 @@ public class Jackson2ObjectMapperBuilder {
|
|||
private static class XmlObjectMapperInitializer {
|
||||
|
||||
public ObjectMapper create() {
|
||||
return new XmlMapper(xmlInputFactory());
|
||||
}
|
||||
|
||||
public ObjectMapper create(boolean defaultUseWrapper) {
|
||||
JacksonXmlModule module = new JacksonXmlModule();
|
||||
module.setDefaultUseWrapper(defaultUseWrapper);
|
||||
return new XmlMapper(new XmlFactory(xmlInputFactory()), module);
|
||||
}
|
||||
|
||||
private static final XMLInputFactory xmlInputFactory() {
|
||||
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
|
||||
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
|
||||
inputFactory.setXMLResolver(NO_OP_XML_RESOLVER);
|
||||
return new XmlMapper(inputFactory);
|
||||
return inputFactory;
|
||||
}
|
||||
|
||||
private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
|
||||
|
|
|
@ -324,6 +324,15 @@ public class Jackson2ObjectMapperFactoryBean implements FactoryBean<ObjectMapper
|
|||
this.builder.indentOutput(indentOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define if a wrapper will be used for indexed (List, array) properties or not by
|
||||
* default (only applies to {@link XmlMapper}).
|
||||
* @since 4.3
|
||||
*/
|
||||
public void setDefaultUseWrapper(boolean defaultUseWrapper) {
|
||||
this.builder.defaultUseWrapper(defaultUseWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify features to enable.
|
||||
* @see com.fasterxml.jackson.core.JsonParser.Feature
|
||||
|
|
|
@ -22,9 +22,11 @@ import java.nio.file.Path;
|
|||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
@ -437,6 +439,16 @@ public class Jackson2ObjectMapperBuilderTests {
|
|||
assertTrue(xmlObjectMapper.getClass().isAssignableFrom(XmlMapper.class));
|
||||
}
|
||||
|
||||
@Test // SPR-13975
|
||||
public void defaultUseWrapper() throws JsonProcessingException {
|
||||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.xml().defaultUseWrapper(false).build();
|
||||
assertNotNull(objectMapper);
|
||||
assertEquals(XmlMapper.class, objectMapper.getClass());
|
||||
ListContainer<String> container = new ListContainer<>(Arrays.asList("foo", "bar"));
|
||||
String output = objectMapper.writeValueAsString(container);
|
||||
assertThat(output, containsString("<list>foo</list><list>bar</list></ListContainer>"));
|
||||
}
|
||||
|
||||
|
||||
public static class CustomIntegerModule extends Module {
|
||||
|
||||
|
@ -501,4 +513,24 @@ public class Jackson2ObjectMapperBuilderTests {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ListContainer<T> {
|
||||
|
||||
private List<T> list;
|
||||
|
||||
public ListContainer() {
|
||||
}
|
||||
|
||||
public ListContainer(List<T> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void setList(List<T> list) {
|
||||
this.list = list;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue