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

Java Jackson XML:如何将空/空集合序列化为空节点,java,jackson-dataformat-xml,Java,Jackson Dataformat Xml,我使用的是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

我使用的是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);
}
  • 序列化提供程序:

    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);
    
  • 不幸的是,什么都不管用。有人知道如何做到这一点吗

    试验方法:

    @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());
    }
    
    我准备了一个带有示例代码的存储库:


    编辑:

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

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


    编辑:


    我得到了一个如何解决异常问题的提示(请参阅),但它仍然不能解决缺少
    空/空值的问题。

    我需要解决同样的问题,下面是我如何使它工作的:

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

    公共类NullAsEmptyStringSerializer扩展JsonSerializer{
    静态最终JsonSerializer实例=新的NullAsEmptyStringSerializer();
    私有静态最终字符串为空_String=“”;
    私有最终StringSerializer StringSerializer=新StringSerializer();
    @凌驾
    public void序列化(对象值、JsonGenerator gen、SerializerProvider序列化器)
    抛出IOException{
    序列化(空字符串,gen,序列化器);
    }
    }
    
    然后,我创建一个序列化程序修饰符,用我的新序列化程序覆盖bean属性的空序列化程序:

    公共类NullToEmptyPropertySerializerModifier扩展了BeanSerializerModifier{
    @凌驾
    公共列表changeProperties(SerializationConfig配置,
    Bean描述Bean描述,列出Bean属性){
    for(beanProperty编写器beanProperty:beanProperties){
    assignNullSerializer(NullAsEmptyStringSerializer.INSTANCE);
    }
    返回Bean属性;
    }
    }
    
    最后,我将xml映射器配置为使用我的修饰符:

    NullToEmptyPropertySerializerModifier修饰符=新的NullToEmptyPropertySerializerModifier();
    SerializerFactory SerializerFactory=BeanSerializerFactory.instance.withSerializerModifier(修饰符);
    XmlMapper XmlMapper=新的XmlMapper();
    setSerializerFactory(serializerFactory);
    
    尝试查看它是否适用于字符串和对象(
    Person
    Dog
    是虚拟数据持有者对象):

    提供以下输出:

    utku29
    
    为什么需要发出
    ?我使用XSLT技术将这些XML文件转换为人类可读的形式。我想打印
    字段“空”:没有内容,而不是什么都没有。这两个信息完全不同:
    empty/null
    vs
    不存在
    。我检查了它,它不起作用。建议的代码将
    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());
    }
    
    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;
        }
    }
    
    Dog dog = new Dog("bobby");
    Person person = new Person("utku", null, 29, null);
    String serialized = xmlMapper.writeValueAsString(person);
    System.out.println(serialized);