【问题标题】:JsonInclude.Include.NON_DEFAULT not working with custom serializerJsonInclude.Include.NON_DEFAULT 不适用于自定义序列化程序
【发布时间】:2016-07-17 06:37:41
【问题描述】:

我既想使用自定义序列化程序,又想获得 JsonInclude.Include.NON_DEFAULT 称号。当我不使用自定义序列化程序时,它很荣幸,但当我使用自定义序列化程序时,它不是。

这是杰克逊 2.2.2。我目前无法切换到更新版本的 Jackson。

这是一个显示问题的简单示例:

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.IOException;
import java.util.EnumSet;
import java.util.Set;
import java.util.stream.Collectors;    

public class JacksonSerialization
{
    public static void main(String[] args) throws Exception {
        ObjectMapper serializer = new ObjectMapper();

        Foo foo = new Foo();
        foo.setFlags(EnumSet.of(Flag.CC, Flag.BB));
        System.out.println(serializer.writeValueAsString(foo));

        foo = new Foo();
        System.out.println(serializer.writeValueAsString(foo));
    }

    public static enum Flag
    {
        AA,
        BB,
        CC
    }

    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    public static class Foo
    {
        private Set<Flag> flags;

        public Foo() {
            flags = EnumSet.of(Flag.AA);
        }

        @JsonGetter("f")
        @JsonSerialize(using = FlagSetSerializer.class)
        public Set<Flag> getFlags() {
            return flags;
        }

        public void setFlags(Set<Flag> theFlags) {
            flags = theFlags;
        }
    }

    public static class FlagSetSerializer extends JsonSerializer<Set<Flag>>
    {
        @Override
        public void serialize(Set<Flag> value,
                              JsonGenerator jsonGenerator,
                              SerializerProvider serializerProvider) throws IOException {
            String csv = value.stream()
                    .map(Flag::toString)
                    .collect(Collectors.joining(","));
            jsonGenerator.writeString(csv);
        }
    }
}

这是输出:

{"f":"BB,CC"}
{"f":"AA"}

请注意,f 正在被序列化,即使它具有默认值。如果我注释掉 @JsonSerialize 注释,那么我会得到以下输出:

{"f":["BB","CC"]}
{}

然后f 正确地不 被序列化。但当然,事情并没有以我想要的格式序列化。

那么我如何让自定义序列化程序遵守类的 @JsonInclude 注释?

【问题讨论】:

    标签: java json serialization jackson jsonserializer


    【解决方案1】:

    您可能希望按照documentation 实现public boolean isEmpty(SerializerProvider provider, T value),它说:

    public boolean isEmpty(SerializerProvider provider, T value)

    调用方法来检查是否考虑了给定的可序列化值 “空”值(用于抑制空的序列化 值)。

    默认实现将只考虑空值 空。

    根据https://github.com/FasterXML/jackson-databind/issues/730

    另一个可能的麻烦来源是您谈论NON_EMPTY,但您的代码使用NON_DEFAULT。


    而在调试器中挖掘太多导致我建议

    @JsonSerialize(using = FlagSetSerializer.class, include = JsonSerialize.Inclusion.NON_DEFAULT)

    这似乎通过了你的测试。

    问题 似乎在JacksonAnnotationInspector#findSerializationInclusion 中,它首先在属性上查找@JsonInclude 属性,当找不到该属性时,它会查找@JsonSerialize 注释。 @JsonSerialize 包含一个已弃用的 include 属性,其默认值为 ALWAYS。

    我没有深入研究它,但我怀疑弃用/重构设法削减了一些功能。生活吧。

    【讨论】:

    • JsonSerializer 上没有具有该签名的方法。另外,我问的是NON_DEFAULT,而不是NON_EMPTY。
    • 感谢关于 NON_EMPTY 与 NON_DEFAULT 的说明。我已编辑问题以修复问题中的错误。
    • 您使用的是哪个版本的 Jackson?你可能想看看public boolean isEmpty(T value)。但是,如果您实际上正在寻找 NON_DEFAULT 的处理方式,那么所有这些都可能无关紧要。
    • 是的。我实际上正在查看NON_DEFAULT,因为我已经更正了要说的问题。
    • 我用解决方案更新了答案,并分析了为什么在您的特定版本的库中存在问题
    猜你喜欢
    • 2012-10-26
    • 2020-04-20
    • 1970-01-01
    • 2017-06-16
    • 2013-01-06
    • 2019-09-20
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    相关资源
    最近更新 更多