微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java – Jackson:忽略空@XmlWrapperElement集合中的空格

使用Jackson和jackson-dataformat-xml 2.4.4,我试图反序列化一个XML文档,其中用@XmlWrapperElement注释的集合可能没有元素,但XML包含空格(在我的例子中是一个换行符). Jackson在此内容上抛出JsonMappingException,并显示消息“无法从VALUE_STRING标记中反序列化java.util.ArrayList的实例”.我无法改变XML的生成方式.

例:

static class Outer {
    @XmlElementWrapper
    List<Inner> inners;
}

static class Inner {
    @XmlValue
    String foo;
}
ObjectMapper mapper = new XmlMapper().registerModules(new JaxbAnnotationModule());
String xml = "<outer><inners>\n</inners></outer>";
Outer outer = mapper.readValue(xml, Outer.class);

以下变通办法不起作用:

>启用DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY:在这种情况下,Jackson希望使用空格作为内容来实例化Inner的虚假实例.
>为String和集合类型创建此字段的setter.在这种情况下,我得到一个JsonMappingException(“属性的冲突setter定义”inners“”).
>在similar Stackoverflow question,建议将杰克逊降级到2.2.3.这不能解决我的问题.

有什么建议?

编辑:我可以通过包装CollectionDeserializer并检查空白标记解决此问题.然而,这看起来非常脆弱,例如我不得不重写另一个方法来重新包装对象.我可以发布解决方法,但更清洁的方法会更好.

解决方法:

此问题的解决方法是包装标准CollectionDeserializer以返回包含空格的标记的空集合并注册新的Deserializer.我将代码放入模块中,以便轻松注册

import java.io.IOException;
import java.util.Collection;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.deser.std.CollectionDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.CollectionType;


public class XmlWhitespaceModule extends SimpleModule {
    private static class CustomizedCollectionDeserialiser extends CollectionDeserializer {

        public CustomizedCollectionDeserialiser(CollectionDeserializer src) {
            super(src);
        }

        private static final long serialVersionUID = 1L;

        @SuppressWarnings("unchecked")
        @Override
        public Collection<Object> deserialize(JsonParser jp, DeserializationContext ctxt)
                throws IOException, JsonProcessingException {
            if (jp.getCurrentToken() == JsonToken.VALUE_STRING
                    && jp.getText().matches("^[\\r\\n\\t ]+$")) {
                return (Collection<Object>) _valueInstantiator.createUsingDefault(ctxt);
            }
            return super.deserialize(jp, ctxt);
        }

        @Override
        public CollectionDeserializer createContextual(DeserializationContext ctxt,
                BeanProperty property) throws JsonMappingException {
            return new CustomizedCollectionDeserialiser(super.createContextual(ctxt, property));
        }
    }

    private static final long serialVersionUID = 1L;

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyCollectionDeserializer(
                    DeserializationConfig config, CollectionType type,
                    BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                if (deserializer instanceof CollectionDeserializer) {
                    return new CustomizedCollectionDeserialiser(
                        (CollectionDeserializer) deserializer);
                } else {
                    return super.modifyCollectionDeserializer(config, type, beanDesc,
                        deserializer);
                }
            }
        });
    }

}

之后,您可以将它添加到您的ObjectMapper中,如下所示:

ObjectMapper mapper = new XmlMapper().registerModule(new XmlWhitespaceModule());

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。