我正在尝试使用 Jackson 反序列化 JSON 结构,并且正在使用如下所示的 DTO:
public class RootLevelDTO {
private List<ComplexEntry> complexEntries;
// ... other fields, not relevant
}
现在,ComplexEntry
可以有子类型,那些有枚举类型的属性等等。如果通信的另一方更新他们的 API,例如添加另一个子类型或添加枚举文字。
我想做的是告诉 jackson :
- 如果您在
complexEntries
反序列化过程中遇到任何数据绑定(bind)错误领域... - ...不要抛出异常,而是忽略此条目并继续下一个条目。
到目前为止我尝试的是使用 ComplexEntry
的委托(delegate)解串器:
public class ComplexEntryDeserializer extends StdDeserializer<ComplexEntry> {
private StdDeserializer<ComplexEntry> delegate;
public ComplexEntryDeserializer(StdDeserializer<ComplexEntry> delegate){
this.delegate = delegate;
}
public ComplexEntry deserialize(JsonParser p, DeserializationContext ctxt){
try {
return this.delegate.deserialize(p, ctxt);
}catch(Exception e){
// the list entry failed to deserialize, but we have to return *something* here
return null;
}
}
// ... other mandatory methods, not relevant here
}
这个解决方案有一个问题,它会引入null
值 complexEntries
列表,然后我必须使用 Converter
显式删除它.
这个问题有更优雅的解决方案吗?
最佳答案
经过大量修改,我最终得到了以下解决方案。它不需要任何额外的 jackson 模块或其他魔法,只需要一个(特定的)反序列化器。
DTO:
public class RootLevelDTO {
// use a custom deserializer for the list
@JsonDeserialize(using = ListOfComplexEntryDeserializer.class)
private List<ComplexEntry> complexEntries;
}
解串器:
public class ListOfComplexEntryDeserializer extends JsonDeserializer<List<ComplexEntry>> {
@Override
public List<ComplexEntry> deserialize(JsonParser p, DeserializationContext ctxt) {
List<ComplexEntry> resultList = new ArrayList<>();
while(p.nextToken() != JsonToken.END_ARRAY){
try {
// delegate the deserialization of the individual list entries to the standard deserializers
resultList.add(ctxt.readValue(p, ComplexEntry.class))
}catch(Exception e){
// log that the entry wasn't deserialized properly
System.out.println("ComplexEntry could not be read and will be ignored.");
}
}
return resultList;
}
}
重要免责声明:虽然上面的代码可以工作,但您不应该在设计上追求它。我真的已经陷入困境,别无选择(由于我无法控制的外部因素),对于这种情况,它是有效的。
关于java - 如何忽略导致 jackson 反序列化错误的列表条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63559544/