Java 我如何忽略一个';使用Jackson序列化列表中的哪些内容?

Java 我如何忽略一个';使用Jackson序列化列表中的哪些内容?,java,serialization,jackson,Java,Serialization,Jackson,我目前正在使用序列化程序中的一个大类,但我似乎找不到如何忽略/跳过被序列化的特定类。我尝试过像推荐的那样使用注释@JsonIgnoreType,但这似乎只适用于实际字段(而不是列表中的条目)。我还尝试使用@JsonIgnoreType标记我想忽略的类,并使用自定义注释内省器,但它只保存空类而不包含字段(className除外): 结果: { "scripts" : [ { "className" : "com.JsonEx

我目前正在使用序列化程序中的一个大类,但我似乎找不到如何忽略/跳过被序列化的特定类。我尝试过像推荐的那样使用注释@JsonIgnoreType,但这似乎只适用于实际字段(而不是列表中的条目)。我还尝试使用@JsonIgnoreType标记我想忽略的类,并使用自定义注释内省器,但它只保存空类而不包含字段(className除外):

结果:

{
    "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());
        }
    }

}
package-com;
导入com.fasterxml.jackson.annotation.JsonProperty;
导入com.fasterxml.jackson.annotation.JsonTypeInfo;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.ObjectWriter;
导入com.fasterxml.jackson.databind.SerializationFeature;
导入java.io.File;
导入java.util.ArrayList;
导入java.util.List;
/**
*@作者clem585
*@创建于2021年2月28日-凌晨1:43
*/
公共类JsonExemple{
公共静态void main(字符串[]args){
试一试{
//创建JSON编写器
ObjectMapper saveMapper=新的ObjectMapper()
.configure(SerializationFeature.FAIL\u在\u空\u bean上,false);
ObjectWriter saveWriter=saveMapper.writer().withDefaultPrettyPrinter();
//实例化我要保存的类
exampleClass exampleClass=新的exampleClass();
//创建空文件
File File=新文件(“D:/Desktop/example.json”);
新文件(“D:/Desktop/”).mkdirs();
createNewFile();
saveWriter.writeValue(文件,ExampleClass);
System.out.println(“D驱动器桌面上保存的example.json”);
}捕获(例外e){
System.out.println(“试图保存示例的异常”);
e、 printStackTrace();
}
}
私有静态类ScriptB扩展脚本{
@JsonProperty
私人内部控制;
公共脚本b(){
保持=50;
}
}
//忽略这个类
私有静态类ScriptA扩展脚本{
私人住宅;
公共脚本(){
dontKeep=25;
}
}
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS,property=“className”)
私有静态抽象类脚本{
}
私有静态类exampleClass{
@JsonProperty
私有列表脚本;
公共示例类(){
scripts=newarraylist();
scripts.add(新ScriptA());
添加(新的ScriptB());
}
}
}

对于按特定类型筛选列表,Jackson似乎有点固执<如果您在ExampleClass中具有该类型的属性,则ScriptA中的code>@JsonIgnoreType将起作用,但如果它是列表中可能的子类型,则不起作用

所以你需要一个变通办法。一种是ExampleClass的自定义序列化程序,或者在将脚本序列化为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());
    }
}
私有静态类exampleClass{
私有列表脚本;
公共示例类(){
scripts=newarraylist();
scripts.add(新ScriptA());
添加(新的ScriptB());
}
@JsonProperty(“脚本”)
私有列表过滤器scriptsforjson(){
返回scripts.stream()
.filter(s->!(脚本的s实例))
.collect(Collectors.toList());
}
}
如您所见,此代码不直接注释属性,而是使用私有的“getter”。Jackson将使用该方法序列化名为“scripts”的属性(您可以在此处使用任何名称,但我们希望模拟实际的“scripts”属性),以便该方法可以过滤列表以删除所有ScriptA实例。它也被标记为
private
,因为我们不希望任何其他类使用该方法,它只存在于Jackson中


如果您在代码中的其他地方使用了ScriptA类,那么您仍然应该尽可能使用
@JsonIgnoreType
@JsonIgnore
注释,并且仅在注释失败时使用上述解决方法。

谢谢!我刚刚使用了这个,但将过滤器修改为按注释过滤,使其更容易应用于多个脚本:
.filter(s->s.getClass().getAnnotation(JsonIgnoreType.class)==null)
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());
    }
}