[英]How do I ignore a class that's within a list from being serialized using Jackson?
I'm currently using 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.我目前正在使用Jackson在我的程序中序列化一个大的 class ,但我似乎找不到如何忽略/跳过特定类的序列化。 I've tried using the annotation @JsonIgnoreType like it was recommended here , but that only seems to work for actual fields (not entries in a list).
我已经尝试过使用注释 @JsonIgnoreType ,就像这里推荐的那样,但这似乎只适用于实际字段(而不是列表中的条目)。 I've also tried tagging the classes I want to ignore with @JsonIgnoreType and using a custom annotation introspector, but it just saves the empty classes without the fields (except for className):
我还尝试使用@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;
}
}
Result:结果:
{
"scripts" : [ {
"className" : "com.JsonExemple$ScriptA"
}, {
"className" : "com.JsonExemple$ScriptB",
"keep" : 50
} ]
}
Here's the snippet:这是片段:
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 seems to be a bit stubborn when it comes to filter lists by a certain type. Jackson 在按某种类型过滤列表时似乎有点固执。
@JsonIgnoreType
in ScriptA would work if you have a property of that type in ExempleClass, but not when it is a possible sub-type in a list.如果您在 ExempleClass 中有该类型的属性,则
@JsonIgnoreType
中的 @JsonIgnoreType 将起作用,但当它是列表中可能的子类型时则不起作用。
So you need a workaround instead.所以你需要一个解决方法。 One would a custom serializer for ExempleClass, or you filter the scripts prior serializing them to JSON:
一种是为 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());
}
}
As you can see, this code doesn't annotate the property directly, but uses a private "getter" instead.如您所见,此代码不直接注释属性,而是使用私有“getter”。 Jackson will use that method to serialize the property named "scripts" (you can use any name here, but we want to imitate the actual "scripts" property), so that method can filter the list to remove all ScriptA instances.
Jackson 将使用该方法序列化名为“scripts”的属性(您可以在此处使用任何名称,但我们想模仿实际的“scripts”属性),以便该方法可以过滤列表以删除所有 ScriptA 实例。 It is also marked as
private
, because we don't want any other classes to use that method, it exists only for Jackson.它也被标记为
private
,因为我们不希望任何其他类使用该方法,它只存在于 Jackson 中。
If you use the class ScriptA somewhere else in your code, then you should still try to use @JsonIgnoreType
and @JsonIgnore
annotations whenever possible and only use the above mentioned workaround, when those annotations fail.如果您在代码的其他位置使用 class ScriptA,那么您仍应尽可能尝试使用
@JsonIgnoreType
和@JsonIgnore
注释,并且仅在这些注释失败时使用上述解决方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.