【问题标题】:Jackson global settings to deserialise array to custom list implementationJackson 全局设置将数组反序列化为自定义列表实现
【发布时间】:2019-06-12 19:54:13
【问题描述】:

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

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

PS:我的 Jackson 版本是 2.9.7

【问题讨论】:

    标签: java json jackson fasterxml jackson2


    【解决方案1】:

    一般的解决方案是使用自定义模块。您可以定义要用于集合的类。 Guava 有一个 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 类与List 实现绑定,您需要使用SimpleModule 类添加一些额外的配置。因此,您的 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 -&gt; empty,请参阅此问题:

    1. Jackson deserializer - change null collection to empty one

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

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

    【讨论】:

    • 谢谢,Michał,我正在寻找 +1
    【解决方案2】:

    我不认为存在这种简单的方法,因为CollectionDeserializer 在解析之前创建集合实例。因此,出于此目的,您需要创建自定义反序列化器。

    但我不确定=))

    【讨论】:

      猜你喜欢
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-27
      • 2014-08-02
      • 2019-02-08
      • 2016-02-13
      • 2011-04-12
      相关资源
      最近更新 更多