JsonInclude.Include.NON_DEFAULT not working with custom serializer

我只是一个虾纸丫 提交于 2019-12-14 01:19:37

问题


I want to both use a custom serializer and have the JsonInclude.Include.NON_DEFAULT designation be honored. When I don't use a custom serializer it is honored but when I do use a custom serializer it is not.

This is Jackson 2.2.2. I do not presently have the option to switch to a newer version of Jackson.

Here's a simple example that shows the problem:

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);
        }
    }
}

And here's the output:

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

Note that f is being serialized even when it has the default value. If I comment out the @JsonSerialize annotation then I get the following output:

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

Then f properly does not get serialized. But of course things are not being serialized in the format I want.

So how do I get the custom serializer to honor the class's @JsonInclude annotation?


回答1:


You probably want to implement public boolean isEmpty(SerializerProvider provider, T value) as per the documentation, which says:

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.

As per https://github.com/FasterXML/jackson-databind/issues/730

Another possible source of trouble is that you talk about NON_EMPTY but you code uses NON_DEFAULT.


And rather too much digging in the debugger leads me to suggest

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

Which seems to pass your tests.

The problem seems to be in JacksonAnnotationInspector#findSerializationInclusion, which first looks for a @JsonInclude attribute on the property, and when it fails to find that, it looks for a @JsonSerialize annotation. @JsonSerialize includes a deprecated include property, which has a default value of ALWAYS.

I've not looked into it too deeply, but I suspect a deprecation/refactor managed to slice off some functionality. C'est la vie.



来源:https://stackoverflow.com/questions/36288834/jsoninclude-include-non-default-not-working-with-custom-serializer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!