提问者:小点点

Jackson XML:如何将空/null集合序列化为空节点


我正在使用Jackson XML 2.8.9,不幸的是,我找不到任何方法将空/空集合序列化为空节点。

负责序列化为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);
}

我尝试使用:

>

mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);

序列化提供程序:

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功能:

mapper.configure(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL, false);

不幸的是,什么都不管用。有人知道如何实现它吗?

试验方法:

@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;</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

编辑:

我扩展了test-toXml方法,并进行了一些代码清理。

我还尝试创建一个基于模块和序列化修改器的解决方案。不幸的是,两人都以失败告终。我在jackson dataformat xml中创建了一个问题:

  • 使用自定义实现重写映射序列化程序后的NPE(XmlBeanSerializerModifier.modifyMapSerializer)

编辑:

我得到了一个如何解决异常问题的提示(请参阅使用自定义实现(XmlBeanSerializerModifier.modifyMapSerializer)重写映射序列化器后的NPE),但它仍然不能解决缺少空/null值的问题。


共1个答案

匿名用户

我需要解决同样的问题,以下是我如何让它发挥作用的:

首先,我创建一个序列化程序,将null序列化为空字符串:

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属性的空序列化器:

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映射器配置为使用我的修饰符:

NullToEmptyPropertySerializerModifier modifier = new NullToEmptyPropertySerializerModifier();
SerializerFactory serializerFactory = BeanSerializerFactory.instance.withSerializerModifier(modifier);
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.setSerializerFactory(serializerFactory);

尝试查看它是否适用于字符串和对象(Person和Dog是虚拟数据持有者对象):

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>