【问题标题】:How can I get Jackson to serialize an unsorted set in sorted order?如何让杰克逊按排序顺序序列化未排序的集合?
【发布时间】:2020-01-08 22:16:56
【问题描述】:

我有一个 Java 对象,其中包含一组未排序的可比较对象。有什么方法可以让 Jackson 在将其序列化为 JSON 列表之前对其进行排序?

我想要这种行为,以便在用 Java 表示时相等的对象确定性地生成相同的 JSON。

杰克逊有什么设置可以做到这一点吗?还是我最好的选择是编写自定义序列化程序?

单个自定义序列化程序能否适用于所有Set<T> T implements Comparable

这个问题不是 jackson to sort the response by using the field name alone 的重复,它询问如何对 Map 中的键进行排序。这个问题是关于对 Set 中的元素进行排序的。

【问题讨论】:

  • 这个问题其实不是重复的;请参阅上面的编辑

标签: java json serialization jackson set


【解决方案1】:

即使您使用Set 接口的HashSet 实现,当两个集合包含相同的对象时,它也会产生相同的结果。因此,您无需对集合进行排序即可为两个不同但相等(包含相同对象)的集合生成相同的 JSON。

但如果你想强制 Jackson 在序列化之前对集合进行排序,你需要实现自定义序列化器。

我们只能为Set 注册序列化程序,它将用于包含Comparable 对象的集合和不包含对象的集合,因此必须在自定义实现中进行检查。

示例实现如下所示:

class SortedSetJsonSerializer extends JsonSerializer<Set> {

    @Override
    public void serialize(Set set, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (set == null) {
            gen.writeNull();
            return;
        }

        gen.writeStartArray();
        if (!set.isEmpty()) {
            // create sorted set only if it itself is not already SortedSet
            if (!SortedSet.class.isAssignableFrom(set.getClass())) {
                Object item = set.iterator().next();
                if (Comparable.class.isAssignableFrom(item.getClass())) {
                    // and only if items are Comparable
                    set = new TreeSet(set);
                }
            }
            for (Object item : set) {
                gen.writeObject(item);
            }
        }
        gen.writeEndArray();
    }
} 

以及示例用法:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.IntStream;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        Set<Integer> ints = newSet();

        SimpleModule module = new SimpleModule();
        module.addSerializer(Set.class, new SortedSetJsonSerializer());
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(module);

        System.out.println(mapper.writeValueAsString(new MyModel(ints)));
    }

    private static Set<Integer> newSet() {
        Set<Integer> ints = new HashSet<>();
        IntStream.range(10, 20).forEach(ints::add);

        return ints;
    }
}

class MyModel {
    private Set<Integer> integers;

    public MyModel(Set<Integer> integers) {
        this.integers = integers;
    }

    public Set<Integer> getIntegers() {
        return integers;
    }

    public void setIntegers(Set<Integer> integers) {
        this.integers = integers;
    }
}

打印:

{"integers":[10,11,12,13,14,15,16,17,18,19]}

【讨论】:

    猜你喜欢
    • 2017-12-09
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 2018-09-04
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    相关资源
    最近更新 更多