如何序列化使用 Jackson 扩展 TreeSet 的 class?

How to serialize a class that extends TreeSet with Jackson?

Class A 看起来像这样:

@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
public final class A extends TreeSet<B> {

    private final a;
    private b;
    private c;

    public A(a, b, c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}

Class乙:

@Data
@AllArgsConstructor
@EqualsAndHashCode
@ToString
public final class B  {
    private final int x;
    private final double y;
}

当我使用 Jackson 序列化一个 class 对象时:

jsonString = objectMapper.writeValueAsString(class_a_object);

我得到一个 json 这样的数组:

[
  {
    "x": 3,
    "y": 3.23
  },
  {
    "x": 4,
    "y": 2.12
  },...
]

但是缺少成员变量a,b,c。有什么办法可以将它们包含在 json 字符串中吗?

Jackson 将 class A 识别为集合并注册 CollectionSerializer 以序列化 A 的实例。我们可以修改默认序列化器并提供自定义序列化器。我们可以使用 BeanSerializerModifier 来做到这一点,并在自定义实现中重用集合序列化程序。要生成有效的 JSON,您需要为设置值提供 属性 名称。

示例:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.type.CollectionType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

import java.io.File;
import java.io.IOException;
import java.util.TreeSet;

public class ModifyCollectionSerializerApp {
    public static void main(String[] args) throws IOException {
        A a = new A(1, 2);
        a.add(new B(22, 2.2));
        a.add(new B(33, 3.3));

        SimpleModule aModule = new SimpleModule();
        aModule.setSerializerModifier(new ABeanSerializerModifier());
        JsonMapper mapper = JsonMapper.builder()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .addModule(aModule)
                .build();
        String json = mapper.writeValueAsString(a);
        System.out.println(json);
    }
}

class ABeanSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config, CollectionType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {
        return new AJsonSerializer(serializer);
    }
}

class AJsonSerializer extends JsonSerializer<A> {

    private final JsonSerializer valuesSerializer;

    AJsonSerializer(JsonSerializer valuesSerializer) {
        this.valuesSerializer = valuesSerializer;
    }

    @Override
    public void serialize(A value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeNumberField("a", value.getA());
        gen.writeNumberField("b", value.getB());
        gen.writeFieldName("values");
        valuesSerializer.serialize(value, gen, serializers);
        gen.writeEndObject();
    }
}

@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
class A extends TreeSet<B> {

    private final int a;
    private final int b;
}

@Data
@AllArgsConstructor
@EqualsAndHashCode
@ToString
class B implements Comparable<B> {
    private final int x;
    private final double y;

    @Override
    public int compareTo(B o) {
        return this.x - o.x;
    }
}

以上代码打印:

{
  "a" : 1,
  "b" : 2,
  "values" : [ {
    "x" : 22,
    "y" : 2.2
  }, {
    "x" : 33,
    "y" : 3.3
  } ]
}