JsonInclude.Include.NON_DEFAULT无法使用自定义序列化程序

时间:2016-03-29 15:37:44

标签: 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注释?

1 个答案:

答案 0 :(得分:2)

您可能希望根据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属性,当它找不到该属性时,它会查找{ {1}}注释。 @JsonSerialize包含已弃用的@JsonSerialize属性,其默认值为include

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