如何忽略使用 Jackson 序列化的列表中的 class?
How do I ignore a class that's within a list from being serialized using Jackson?
我目前正在使用 Jackson to serialize a big class in my program, but I can't seem to find how to ignore/skip specific classes from being serialized. I've tried using the annotation @JsonIgnoreType like it was recommended here,但这似乎只适用于实际字段(不适用于列表中的条目)。我也尝试过标记 类 我想用 @JsonIgnoreType 忽略并使用自定义注释内省器,但它只保存没有字段的空 类 (className 除外):
saveMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
return super.hasIgnoreMarker(m) || m.getDeclaringClass().getAnnotation(JsonIgnoreType.class) != null;
}
});
...
@JsonIgnoreType
private static class ScriptA extends Script {
private int dontKeep;
public ScriptA() {
dontKeep = 25;
}
}
结果:
{
"scripts" : [ {
"className" : "com.JsonExemple$ScriptA"
}, {
"className" : "com.JsonExemple$ScriptB",
"keep" : 50
} ]
}
这是片段:
package com;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author clem585
* @created 28/02/2021 - 1:43 AM
*/
public class JsonExemple {
public static void main(String[] args) {
try {
// create Jackson JSON writer
ObjectMapper saveMapper = new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
ObjectWriter saveWriter = saveMapper.writer().withDefaultPrettyPrinter();
// instantiate class I want to save
ExempleClass exempleClass = new ExempleClass();
// create empty file
File file = new File("D:/Desktop/exemple.json");
new File("D:/Desktop/").mkdirs();
file.createNewFile();
saveWriter.writeValue(file, exempleClass);
System.out.println("Saved exemple.json on the desktop of the D drive");
} catch (Exception e) {
System.out.println("Exception attempting to save exemple");
e.printStackTrace();
}
}
private static class ScriptB extends Script {
@JsonProperty
private int keep;
public ScriptB() {
keep = 50;
}
}
// ignore this class
private static class ScriptA extends Script {
private int dontKeep;
public ScriptA() {
dontKeep = 25;
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
private static abstract class Script {
}
private static class ExempleClass {
@JsonProperty
private List<Script> scripts;
public ExempleClass() {
scripts = new ArrayList<>();
scripts.add(new ScriptA());
scripts.add(new ScriptB());
}
}
}
Jackson 在按某种类型筛选列表时似乎有点固执。如果您在 ExempleClass 中有该类型的 属性,ScriptA 中的 @JsonIgnoreType
将起作用,但当它是列表中可能的子类型时则不起作用。
所以你需要一个解决方法。一个是 ExempleClass 的自定义序列化程序,或者您在将脚本序列化为 JSON:
之前过滤脚本
private static class ExempleClass {
private List<Script> scripts;
public ExempleClass() {
scripts = new ArrayList<>();
scripts.add(new ScriptA());
scripts.add(new ScriptB());
}
@JsonProperty("scripts")
private List<Script> filterScriptsForJson() {
return scripts.stream()
.filter(s -> !(s instanceof ScriptA))
.collect(Collectors.toList());
}
}
如您所见,这段代码没有直接注解属性,而是使用了一个私有的“getter”。 Jackson 将使用该方法序列化名为“scripts”的 属性(您可以在此处使用任何名称,但我们要模仿实际的“scripts”属性),以便该方法可以过滤列表以删除所有 ScriptA 实例。它也被标记为 private
,因为我们不希望任何其他 classes 使用该方法,它只存在于 Jackson。
如果您在代码的其他地方使用 class ScriptA,那么您仍应尽可能尝试使用 @JsonIgnoreType
和 @JsonIgnore
注释,并且仅使用上述解决方法,当这些注释失败时。
我目前正在使用 Jackson to serialize a big class in my program, but I can't seem to find how to ignore/skip specific classes from being serialized. I've tried using the annotation @JsonIgnoreType like it was recommended here,但这似乎只适用于实际字段(不适用于列表中的条目)。我也尝试过标记 类 我想用 @JsonIgnoreType 忽略并使用自定义注释内省器,但它只保存没有字段的空 类 (className 除外):
saveMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
return super.hasIgnoreMarker(m) || m.getDeclaringClass().getAnnotation(JsonIgnoreType.class) != null;
}
});
...
@JsonIgnoreType
private static class ScriptA extends Script {
private int dontKeep;
public ScriptA() {
dontKeep = 25;
}
}
结果:
{
"scripts" : [ {
"className" : "com.JsonExemple$ScriptA"
}, {
"className" : "com.JsonExemple$ScriptB",
"keep" : 50
} ]
}
这是片段:
package com;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author clem585
* @created 28/02/2021 - 1:43 AM
*/
public class JsonExemple {
public static void main(String[] args) {
try {
// create Jackson JSON writer
ObjectMapper saveMapper = new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
ObjectWriter saveWriter = saveMapper.writer().withDefaultPrettyPrinter();
// instantiate class I want to save
ExempleClass exempleClass = new ExempleClass();
// create empty file
File file = new File("D:/Desktop/exemple.json");
new File("D:/Desktop/").mkdirs();
file.createNewFile();
saveWriter.writeValue(file, exempleClass);
System.out.println("Saved exemple.json on the desktop of the D drive");
} catch (Exception e) {
System.out.println("Exception attempting to save exemple");
e.printStackTrace();
}
}
private static class ScriptB extends Script {
@JsonProperty
private int keep;
public ScriptB() {
keep = 50;
}
}
// ignore this class
private static class ScriptA extends Script {
private int dontKeep;
public ScriptA() {
dontKeep = 25;
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "className")
private static abstract class Script {
}
private static class ExempleClass {
@JsonProperty
private List<Script> scripts;
public ExempleClass() {
scripts = new ArrayList<>();
scripts.add(new ScriptA());
scripts.add(new ScriptB());
}
}
}
Jackson 在按某种类型筛选列表时似乎有点固执。如果您在 ExempleClass 中有该类型的 属性,ScriptA 中的 @JsonIgnoreType
将起作用,但当它是列表中可能的子类型时则不起作用。
所以你需要一个解决方法。一个是 ExempleClass 的自定义序列化程序,或者您在将脚本序列化为 JSON:
之前过滤脚本private static class ExempleClass {
private List<Script> scripts;
public ExempleClass() {
scripts = new ArrayList<>();
scripts.add(new ScriptA());
scripts.add(new ScriptB());
}
@JsonProperty("scripts")
private List<Script> filterScriptsForJson() {
return scripts.stream()
.filter(s -> !(s instanceof ScriptA))
.collect(Collectors.toList());
}
}
如您所见,这段代码没有直接注解属性,而是使用了一个私有的“getter”。 Jackson 将使用该方法序列化名为“scripts”的 属性(您可以在此处使用任何名称,但我们要模仿实际的“scripts”属性),以便该方法可以过滤列表以删除所有 ScriptA 实例。它也被标记为 private
,因为我们不希望任何其他 classes 使用该方法,它只存在于 Jackson。
如果您在代码的其他地方使用 class ScriptA,那么您仍应尽可能尝试使用 @JsonIgnoreType
和 @JsonIgnore
注释,并且仅使用上述解决方法,当这些注释失败时。