将数组反序列化为自定义列表实现的 Jackson 全局设置

Jackson global settings to deserialise array to custom list implementation

默认情况下,Jackson 使用 java.util.ArrayList 反序列化 JSON 数组。而不是这个,我想使用自定义实现。例如,Guava ImmutableList 如果值存在,或 Collection.emptyList() 如果 JSON 数组为空或 null。

我想为 ObjectMapper 进行全局配置。有没有简单的方法可以做到这一点?

PS: 我的 Jackson 版本是 2.9.7

我认为不存在简单的方法,因为 CollectionDeserializer 在解析之前创建集合实例。因此,为此目的,您需要创建自定义解串器。

但我不确定=))

一般的解决方案是使用自定义模块。您可以定义要用于集合的 classes。对于番石榴,有一个 Maven 模块:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-guava</artifactId>
    <version>x.y.z</version>
</dependency>

现在,您可以注册您的新模块:

ObjectMapper mapper = new ObjectMapper();
// register module with object mapper
mapper.registerModule(new GuavaModule());

现在,您可以在 POJO 中定义您想要列表的不可变实现。

class Pojo {

    private ImmutableList<Integer> ints;

    public ImmutableList<Integer> getInts() {
        return ints;
    }

    public void setInts(ImmutableList<Integer> ints) {
        this.ints = ints;
    }

    @Override
    public String toString() {
        return "Pojo{" +
                "ints=" + ints + " " + ints.getClass() + '}';
    }
}

及以下示例:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());

String json = "{\"ints\":[1,2,3,4]}";

System.out.println(mapper.readValue(json, Pojo.class));

打印:

Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}

如果您不想将 POJO class 与 List 实现联系起来,您需要使用 SimpleModule class 添加一些额外的配置。因此,您的 POJO 如下所示:

class Pojo {

    private List<Integer> ints;

    public List<Integer> getInts() {
        return ints;
    }

    public void setInts(List<Integer> ints) {
        this.ints = ints;
    }

    @Override
    public String toString() {
        return "Pojo{" +
                "ints=" + ints + " " + ints.getClass() + '}';
    }
}

您的示例如下所示:

SimpleModule useImmutableList = new SimpleModule("UseImmutableList");
useImmutableList.addAbstractTypeMapping(List.class, ImmutableList.class);

GuavaModule module = new GuavaModule();

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.registerModule(useImmutableList);

String json = "{\"ints\":[1,2,3,4]}";

System.out.println(mapper.readValue(json, Pojo.class));

以上代码打印:

Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}

当你删除额外的 SimpleModule 上面的代码打印:

Pojo{ints=[1, 2, 3, 4] class java.util.ArrayList}

如果它是空的,我认为使用 Collections.emptyList() 没有任何意义。 Guava 的模块使用 RegularImmutableList 表示非空和空数组。

要转换 null -> empty 请看这个问题:

但我建议在 POJO 中将其设置为 empty,如下所示:

private List<Integer> ints = Collections.emptyList();