英文:
Can not deserialize empty content within tags when newline met
问题
以下是翻译好的内容:
有以下两个类:
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Structure {
@JacksonXmlProperty
private Info info;
}
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor
@AllArgsConstructor
public class Info {
private Subinfo subinfo;
}
进行反序列化操作:
private static final XmlMapper XML_MAPPER = new XmlMapper();
Structure structure = XML_MAPPER.readValue(input, Structure.class);
其中 input
是我的 XML(见下文)
出现异常:
com.fasterxml.jackson.databind.exc.MismatchedInputException: 无法构造 `com.test.models.Info` 的实例(尽管至少存在一个创建者):没有可用于从字符串值反序列化的String-argument构造函数/工厂方法(' ')
这个 Jackson 特性没有起作用:
XML_MAPPER.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
我失败的 XML 如下:
<?xml version='1.0' encoding='UTF-8' ?>
<Structure>
<Info>
</Info>
</Structure>
对于这个 XML,反序列化正常工作:
<?xml version='1.0' encoding='UTF-8' ?>
<Structure>
<Info/>
</Structure>
问题出在标签闭合的方式上:
<Info/>
与 <Info></Info>
。
<Info/>
正常工作,
然而
<Info>
</Info>
在出现换行符时会导致异常。
英文:
Have following 2 classes:<br>
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Structure {
@JacksonXmlProperty
private Info info;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor
@AllArgsConstructor
public class Info{
private Subinfo subinfo;
}
doing deserialization like:
private static final XmlMapper XML_MAPPER = new XmlMapper();
Structure structure = XML_MAPPER.readValue(input, Structure.class);
where input
is my XML(see below)
got exception:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.models.Info` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('
')
this Jackson feature did not help:
XML_MAPPER.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
my XML that failed:
<?xml version='1.0' encoding='UTF-8' ?>
<Structure>
<Info>
</Info>
</Structure>
for this XML deserialization works OK:
<?xml version='1.0' encoding='UTF-8' ?>
<Structure>
<Info/>
</Structure>
The problem is with tag closing approach:
<Info/>
VS <Info></Info>
<Info/>
works OK
while
<Info>
</Info>
causes Exception when line terminators occurred
答案1
得分: 3
如其他人在他们的评论中已经提到的那样,DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
仅将空字符串转换为 null,但是您的 Info 元素内部包含空格和换行符。
其他人无法重现您的问题,因为您要么忘记提到您的代码中还使用了 XML_MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
,要么是您示例 XML 中的 _Info_
实际上应该是 _info_
,否则该元素将被忽略。
要处理空字符串和仅包含空格和/或换行符的字符串,您可以在解析 XML 之前添加以下代码:
XML_MAPPER.addHandler(new DeserializationProblemHandler() {
@Override
public Object handleMissingInstantiator(DeserializationContext ctxt, Class<?> instClass,
ValueInstantiator valueInsta, JsonParser p, String msg) throws IOException {
String value = p.getValueAsString();
// 忽略“空”Info元素
if (instClass.isAssignableFrom(Info.class) && (value.isEmpty() || value.matches("[\\n\\s]+"))) {
return null;
}
return super.handleMissingInstantiator(ctxt, instClass, valueInsta, p, msg);
}
});
如果您想对所有元素都执行此操作,可以简单地忽略 instClass
。
英文:
As others already mentioned in their comments, <code>DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT</code> converts only empty strings to null, but you have spaces and line separators within your Info element.
Others cannot reproduce your problem since you either missed to mention that you also use <code>XML_MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)</code> in your code or Info in your example XML should actually be info, otherwise the element is ignored.
To handle empty strings and strings that only contain spaces and/or line separators you can add the following code before you parse the XML:
XML_MAPPER.addHandler(new DeserializationProblemHandler() {
@Override
public Object handleMissingInstantiator(DeserializationContext ctxt, Class<?> instClass,
ValueInstantiator valueInsta, JsonParser p, String msg) throws IOException {
String value = p.getValueAsString();
// ignore "empty" Info elements
if (instClass.isAssignableFrom(Info.class) && (value.isEmpty() || value.matches("[\n\s]+"))) {
return null;
}
return super.handleMissingInstantiator(ctxt, instClass, valueInsta, p, msg);
}
});
If you want to do this for all elements you can simply ignore <code>instClass</code>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论