java - JsonInclude.Include.NON_DEFAULT 不适用于自定义序列化程序

标签 java json serialization jackson jsonserializer

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

这是 jackson 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 注释?

最佳答案

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

public boolean isEmpty(SerializerProvider provider, T value)

Method called to check whether given serializable value is considered "empty" value (for purposes of suppressing serialization of empty values).

Default implementation will consider only null values to be empty.

根据 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

我没有深入研究它,但我怀疑弃用/重构设法切断了一些功能。 C'est la vie.

关于java - JsonInclude.Include.NON_DEFAULT 不适用于自定义序列化程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36288834/

相关文章:

java - 没有类定义的反序列化对象实例

java - 添加链表到链表,JAVA

java - WLP Microprofile 容错舱壁实现未启动

java - 实例变量初始化的问题

iphone - 将对象序列化为JSON

python - 使用 rPython 包将 numpy 数组导入到 R 中

mysql - 反序列化,再次序列化和更新值

java - 通过java列出hadoop集群中所有yarn应用

javascript - 比较两个数组中的键和值

php - MySQL - 从序列化数组执行 JOIN?