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

时间:2019-01-18 14:17:43

标签: java json jackson fasterxml jackson2

默认情况下,Jackson使用<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent"> <RelativeLayout android:id="@+id/collapse_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentBottom="true" android:layout_alignParentStart="true" android:background="@color/colorPrimary" android:orientation="vertical" android:visibility="visible"> <TextView android:text="Naveen" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/visitor_name" android:textAlignment="center" android:textColor="#fff" android:fontFamily="@font/ubuntu" android:textSize="30dp" android:layout_marginTop="147dp" android:layout_alignParentEnd="true" android:layout_marginEnd="0dp" android:layout_alignParentStart="true" android:layout_marginStart="0dp" android:layout_marginBottom="-57dp" android:layout_alignTop="@+id/imageView7" android:gravity="center"/> <TextView android:text="@string/app_name_short" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/textView11" android:textAlignment="center" android:textColor="#fff" android:fontFamily="@font/ubuntu" android:textSize="50dp" android:layout_marginTop="100dp" android:layout_alignParentEnd="true" android:layout_marginEnd="0dp" android:layout_alignParentStart="true" android:layout_marginStart="0dp"/> <TextView android:text="@string/overlay_visitor_alert" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/textView12" android:layout_below="@+id/textView11" android:textColor="#fff" android:textAlignment="center" android:layout_alignParentStart="true" android:layout_marginStart="0dp" android:layout_alignParentEnd="true" android:layout_marginEnd="0dp"/> <ImageView android:layout_width="149dp" android:layout_height="108dp" app:srcCompat="@drawable/user_round_icon" android:id="@+id/imageView7" android:layout_below="@+id/textView12" android:layout_alignEnd="@+id/textView12" android:layout_alignParentStart="true" android:foregroundGravity="center_horizontal" android:layout_marginTop="32dp" android:layout_marginStart="0dp" android:layout_marginEnd="0dp"/> <ImageView android:layout_width="96dp" android:layout_height="96dp" app:srcCompat="@drawable/overlay_accept" android:id="@+id/visitor_accept" android:layout_alignTop="@+id/visitor_name" android:layout_marginTop="100dp" android:layout_alignParentStart="true" android:layout_marginStart="45dp"/> <ImageView android:layout_width="96dp" android:layout_height="96dp" app:srcCompat="@drawable/overlay_cancel" android:id="@+id/imageView9" android:layout_alignTop="@+id/visitor_name" android:layout_marginTop="100dp" android:layout_toEndOf="@+id/visitor_accept" android:layout_marginStart="100dp"/> </RelativeLayout> </RelativeLayout> 来反序列化JSON数组。取而代之的是,我想使用自定义实现。例如,如果值存在,则使用Guava java.util.ArrayList;如果JSON数组为空或null,则使用ImmutableList

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

PS:我的杰克逊版本为2.9.7

2 个答案:

答案 0 :(得分:2)

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

但我不确定=))

答案 1 :(得分:1)

一般的解决方案是使用自定义模块。您可以定义要用于集合的类。对于番石榴,有一个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 -> empty,请参见以下问题:

  1. Jackson deserializer - change null collection to empty one

但是我建议像下面这样在empty中将其设置为POJO

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