如何序列化使用 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
} ]
}
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
} ]
}