简体   繁体   English

如何忽略使用 Jackson 序列化的列表中的 class?

[英]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.

相关问题 如何使用Jackson来指定某些要序列化为JSON的字段? - How can I specify certain field to be serialized into JSON using Jackson? 使用Jackson对序列化的最终类进行反序列化 - Deserialization of serialized final class using Jackson Java class 实现 JSON 使用 Z7930C951E609E461E85226004ED1 序列化 - Java class implementation for JSON serialized using Jackson 如何将派生属性添加到 Jackson 2 序列化类? - How to add derived properties to a Jackson 2 serialized class? How do I deserialize to Boolean.class from Json object in case insensitive manner using Jackson? - How do I deserialize to Boolean.class from Json object in case insensitive manner using Jackson? 如何使用 Jackson 将 Java class 转换为 XML 文件 - How do I convert a Java class to an XML file using Jackson 如何使用 Jackson 的 ObjectMapper 从 JSON 字符串创建 object? - How do I create an object from a JSON string using Jackson's ObjectMapper? 如何从我在该类中创建的类中访问该类的变量? - How do I access a class's variables from a class that I created within that class? 在写过程中如何告诉Jackson ObjectWriter忽略类成员 - How to tell to Jackson ObjectWriter ignore from class member during write 如何根据被序列化的字段配置 jackson 以使用 JaxbAnnotationIntrospector 或 JacksonAnnotationIntrospector - How to configure jackson to use JaxbAnnotationIntrospector or JacksonAnnotationIntrospector depending on the field being serialized
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM