杰克逊XML:如何将空/空集合序列化为空节点 [英] Jackson XML: how to serialize empty/null collections as empty node
问题描述
我正在使用Jackson XML 2.8.9,不幸的是,我找不到任何将空/空集合序列化为空节点的方法.
I'm using Jackson XML 2.8.9 and unfortunately I cannot find any way to serialize empty/null collections as empty nodes.
负责序列化为XML的方法:
Method responsible for serializing to XML:
protected byte[] toXml(final Collection<ReportView> reports) throws IOException
{
final XmlMapper mapper = new XmlMapper();
// place for code which will solve my problem
return mapper.writerWithDefaultPrettyPrinter().withRootName("report").writeValueAsBytes(reports);
}
我尝试使用:
-
序列化包含:
serialization inclusion:
mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
序列化提供程序:
serialization provider:
final XmlSerializerProvider provider = new XmlSerializerProvider(new XmlRootNameLookup());
provider.setNullValueSerializer(new JsonSerializer<Object>()
{
@Override
public void serialize(final Object value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException
{
jgen.writeString("");
}
});
mapper.setSerializerProvider(provider);
Jackson 2.9.0 EMPTY_ELEMENT_AS_NULL功能:
Jackson 2.9.0 EMPTY_ELEMENT_AS_NULL feature:
mapper.configure(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL, false);
很遗憾,没有任何效果.有人知道如何实现吗?
Unfortunately nothing works. Does anybody know how to achieve it?
测试方法:
@Test
public void testToXml() throws IOException
{
final Map<String, Object> payload = new LinkedHashMap<>();
payload.put("amp", "&");
payload.put("empty", Collections.emptyList());
final Date date = new Date();
final ReportView reportView = new ReportView(payload, date, "system");
// when
final byte[] xmlBytes = reportService.toXml(Arrays.asList(reportView));
// then
final StringBuilder expected = new StringBuilder();
expected.append("<report>");
expected.append(" <item>");
expected.append(" <payload>");
expected.append(" <amp>&</amp>");
expected.append(" <empty></empty>");
expected.append(" </payload>");
expected.append(" <timestamp>" + date.getTime() + "</timestamp>");
expected.append(" <changingUser>system</changingUser>");
expected.append(" </item>");
expected.append("</report>");
final String xmlText = new String(xmlBytes).replace("\n", "").replace("\r", "");
assertThat(xmlText).isEqualTo(expected.toString());
}
ReportView
类:
public class ReportView {
private final Map<String, Object> payload;
private final Date timestamp;
private final String changingUser;
public ReportView(Map<String, Object> payload, Date timestamp, String changingUser) {
this.payload = payload;
this.timestamp= timestamp;
this.changingUser = changingUser;
}
public String getChangingUser() {
return changingUser;
}
public Date getTimestamp() {
return timestamp;
}
public Map<String, Object> getPayload() {
return payload;
}
}
我准备了一个带有示例代码的存储库: https://github.com/agabrys/bugs-reports/tree/master/jackson-xml/empty-elements-serialization
I prepared a repository with example code: https://github.com/agabrys/bugs-reports/tree/master/jackson-xml/empty-elements-serialization
我扩展了测试toXml
方法并进行了一些代码清除.
I extended the test toXml
method and did some code cleanup.
我还尝试创建基于Module
和SerializerModifier
的解决方案.不幸的是,两者都以失败而告终.我在jackson-dataformat-xml
积压订单中创建了一个问题:
I also tried to create a solution based on Module
and SerializerModifier
. Unfortunately both ended with failure. I created an issue in jackson-dataformat-xml
backlog:
我已经暗示了如何解决异常问题(请参阅 NPE用自定义实现(XmlBeanSerializerModifier.modifyMapSerializer)覆盖地图序列化程序后),但仍然不能解决缺少empty/null
值的问题.
I've got a hint how to solve problem with exception (see NPE after overriding map serializer with custom implementation (XmlBeanSerializerModifier.modifyMapSerializer)) but still it does not solve problem with missing empty/null
values.
推荐答案
我需要解决相同的问题,下面是我如何使其工作的方法:
I needed to tackle the same issue, and here's how I got it working:
首先,我创建一个将空值序列化为空字符串的序列化器:
First I create a serializer that serializes nulls as empty string:
public class NullAsEmptyStringSerializer extends JsonSerializer<Object> {
static final JsonSerializer<Object> INSTANCE = new NullAsEmptyStringSerializer();
private static final String EMPTY_STRING = "";
private final StringSerializer stringSerializer = new StringSerializer();
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
stringSerializer.serialize(EMPTY_STRING, gen, serializers);
}
}
然后,我创建一个序列化修改器,用我的新序列化器覆盖Bean属性的空序列化器:
Then I create a serializer modifier, that overwrites the null serializer of the bean properties with my new serializer:
public class NullToEmptyPropertySerializerModifier extends BeanSerializerModifier {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
for (BeanPropertyWriter beanProperty : beanProperties) {
beanProperty.assignNullSerializer(NullAsEmptyStringSerializer.INSTANCE);
}
return beanProperties;
}
}
最后,我将xml映射器配置为使用我的修饰符:
And finally, I configure the xml mapper to use my modifier:
NullToEmptyPropertySerializerModifier modifier = new NullToEmptyPropertySerializerModifier();
SerializerFactory serializerFactory = BeanSerializerFactory.instance.withSerializerModifier(modifier);
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.setSerializerFactory(serializerFactory);
尝试查看它是否适用于字符串和对象(Person
和Dog
是虚拟数据持有者对象):
Trying to see if it's working for strings and objects (Person
and Dog
are dummy data holder objects):
Dog dog = new Dog("bobby");
Person person = new Person("utku", null, 29, null);
String serialized = xmlMapper.writeValueAsString(person);
System.out.println(serialized);
给出以下输出:
<Person><name>utku</name><address></address><age>29</age><dog></dog></Person>
这篇关于杰克逊XML:如何将空/空集合序列化为空节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!