如何忽略在Jackson中导致反序列化错误的列表项?

问题描述

我正在尝试使用Jackson来反序列化JSON结构,并且正在使用如下所示的DTO:

public class RootLevelDTO {
   
    private List<ComplexEntry> complexEntries;
    // ... other fields,not relevant

}

现在,ComplexEntry可以具有子类型,这些子类型具有枚举类型的属性等。如果通信的另一端更新其API,例如,添加一个子类型或添加枚举文字

我想告诉杰克逊:

  • 如果在complexEntries字段反序列化期间遇到任何数据绑定错误...
  • ...不要引发异常,而是忽略该条目并继续下一个

到目前为止,我尝试为ComplexEntry使用委派的反序列化器:

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明确删除它。

有没有更优雅的解决方案?

解决方法

经过大量修补,我得到了以下解决方案。不需要任何其他的杰克逊模块或其他魔术,只需一个(特定的)解串器即可。

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;
    }

}

免责声明:虽然上面的代码有效,但您不应设计这种东西。我真的很愿意在这里碰壁,别无选择(由于无法控制的外部因素),在这种情况下,它是可行的。