杰克逊XML:如何将空/空集合序列化为空节点 [英] Jackson XML: how to serialize empty/null collections as empty node

查看:130
本文介绍了杰克逊XML:如何将空/空集合序列化为空节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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;</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.

    我还尝试创建基于ModuleSerializerModifier的解决方案.不幸的是,两者都以失败而告终.我在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);
    

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

    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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆