首页 > 解决方案 > 使用 Jackson 反序列化的实例化集合类型而不是初始化一个新集合类型?

问题描述

如果我有课

class DTO {
    final MySet<Types> values = MySetWrapper(EnumSet.of(Types.class));

    public MySet getValues() {
        return values;
    }
}

在哪里MySet延伸Set。杰克逊抱怨说

Cannot find a deserializer for non-concrete Collection type MySet

我明白,但我已经实例化了集合。我想要的是让杰克逊add在创建实例后只调用每个值,例如:

DTO o = new DTO();
MySet<Types> values = o.getValues();
for (Types type : jsonArray) {
    values.add(type );
}

我不希望它尝试自己创建一个新集合。

标签: javajackson

解决方案


该错误消息意味着DTO该类已配置(默认或显式)以将valuesJSON 输入的部分反序列化到 DTOvalues字段中DTO

Cannot find a deserializer for non-concrete Collection type MySet

如果您认为 Jackson 不应该直接在该字段上执行反序列化,您可以定义一个构造函数来设置 values并确保 Jackson 不会自动执行反序列化工作:要实现它,删除该字段的 setter(或添加@JsonIgnore它) 以及任何将使用反射反序列化到字段的杰克逊模块。

它会给:

final MySet<Types> values = MySetWrapper(EnumSet.of(Types.class));

@JsonCreator
public MyFoo(Set<Types> values) { 
    this.values.addAll(values);
}

请注意,我在构造函数中指定Set而不是MySet(不应该是问题,因为接口不声明字段),否则您会遇到相同的问题,因为您没有为MySet.
但是,如果您为此实现反序列化器,您当然可以这样做:

public MyFoo(MySet<Types> values) { 
    this.values.addAll(values);
}

推荐阅读