不幸的是,您描述的行为是杰克逊支持的行为,如Github open issue中所示。
使用 JSON 内容,ObjectMapper
您可以启用UNWRAP_ROOT_VALUE
反序列化功能,也许它可能对此有所帮助,尽管我不太确定XmlMapper
.
一种可能的解决方案是自定义反序列化器的实现。
鉴于您的PlainPassword
课程:
@JacksonXmlRootElement(localName = "password")
public class PlainPassword {
public String getPlainPassword() {
return this.plainPassword;
}
public void setPlainPassword(String plainPassword) {
this.plainPassword = plainPassword;
}
private String plainPassword;
}
考虑以下main
方法:
public static void main(String[] args) throws JsonProcessingException {
String xmlString = "<x><plainPassword>12345</plainPassword></x>";
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new SimpleModule().setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
Class<?> beanClass = beanDesc.getBeanClass();
JacksonXmlRootElement annotation = beanClass.getAnnotation(JacksonXmlRootElement.class);
String requiredLocalName = null;
if (annotation != null) {
requiredLocalName = annotation.localName();
}
if (requiredLocalName != null) {
return new EnforceXmlElementNameDeserializer<>(deserializer, beanDesc.getBeanClass(), requiredLocalName);
}
return deserializer;
}
}));
PlainPassword plainPassword = xmlMapper.readValue(xmlString, PlainPassword.class);
System.out.println(plainPassword.getPlainPassword());
}
自定义反序列化器如下所示:
public class EnforceXmlElementNameDeserializer<T> extends StdDeserializer<T> implements ResolvableDeserializer {
private final JsonDeserializer<?> defaultDeserializer;
private final String requiredLocalName;
public EnforceXmlElementNameDeserializer(JsonDeserializer<?> defaultDeserializer, Class<?> beanClass, String requiredLocalName) {
super(beanClass);
this.defaultDeserializer = defaultDeserializer;
this.requiredLocalName = requiredLocalName;
}
@Override
public T deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
String rootName = ((FromXmlParser)p).getStaxReader().getLocalName();
if (!this.requiredLocalName.equals(rootName)) {
throw new IllegalArgumentException(
String.format("Root name '%s' does not match required element name '%s'", rootName, this.requiredLocalName)
);
}
@SuppressWarnings("unchecked")
T itemObj = (T) defaultDeserializer.deserialize(p, ctxt);
return itemObj;
}
@Override public void resolve(DeserializationContext ctxt) throws JsonMappingException {
((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
}
}
ResolvableDeserializer
修改时必须实现BeanDeserializer
,否则反序列化会抛出异常。
该代码基于这个优秀的 SO answer。
测试应该引发IllegalArgumentException
相应的消息:
Root name 'x' does not match required element name 'password'
请根据需要修改异常类型。
相反,如果您使用:
String xmlString = "<password><plainPassword>12345</plainPassword></password>";
在您的main
方法中,它应该可以毫无问题地运行。