杰克逊:忽略空@XmlWrapperElement 集合中的空格
Posted
技术标签:
【中文标题】杰克逊:忽略空@XmlWrapperElement 集合中的空格【英文标题】:Jackson: Ignore whitespace in empty @XmlWrapperElement collection 【发布时间】:2015-02-08 10:27:25 【问题描述】:使用 Jackson 和 jackson-dataformat-xml 2.4.4,我正在尝试反序列化一个 XML 文档,其中带有 @XmlWrapperElement 注释的集合可能有零个元素,但 XML 包含空格(在我的情况下是换行符) . Jackson 在此内容上引发 JsonMappingException,并显示消息“无法反序列化 java.util.ArrayList 的实例超出 VALUE_STRING 令牌”。我无法更改生成 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
的虚假实例。
为字符串和集合类型的该字段创建设置器。在这种情况下,我得到一个 JsonMappingException(“属性“内部”的设置器定义冲突”)。
在similar *** question 中建议将Jackson 降级到2.2.3。这并不能解决我的问题。
有什么建议吗?
编辑:我可以通过包装 CollectionDeserializer 并检查空格标记来解决此问题。然而,这对我来说看起来非常脆弱,例如我不得不重写另一种方法来重新包装对象。我可以发布解决方法,但更清洁的方法会更好。
【问题讨论】:
在@XmlElementWrapper
下面试试@XmlElement(name="Inner")
@guido 也因相同的异常而失败(“无法将 java.util.ArrayList 的实例反序列化出 VALUE_STRING 令牌”)。我编辑了问题以描述一种解决方法,但我仍在寻找一种更简洁的方法。
我遇到了同样的问题。您是如何注册您的 CollectionDeserializer 的?
@StevenBenitez 我在下面用代码添加了答案。
【参考方案1】:
解决此问题的方法是包装标准 CollectionDeserializer
以返回包含空格的令牌的空集合并注册新的反序列化器。我将代码放入Module
,以便轻松注册:
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());
【讨论】:
以上是关于杰克逊:忽略空@XmlWrapperElement 集合中的空格的主要内容,如果未能解决你的问题,请参考以下文章