简体   繁体   English

如果属性名称不等于字段名称,则Jackson定制序列化程序将字段序列化两次

[英]Jackson custom serializer serialize field twice if property name not equal field name

If you use custom serialization, you can get an unexpected effect if property name not equal to field name. 如果使用自定义序列化,则如果属性名称不等于字段名称,则可能会产生意想不到的效果。 Why the field is serialized twice? 为什么字段被序列化两次?

My code sample: 我的代码示例:

class Mode {
    @JsonProperty("mode")
    @JsonSerialize(using = ModeSerializer.class)
    private boolean isPublic;

    public Mode(boolean isPublic) {
        this.isPublic = isPublic;
    }

    public boolean isPublic() {
        return isPublic;
    }
}

Here my custom field serializer: 这是我的自定义字段序列化器:

class ModeSerializer extends JsonSerializer<Boolean> {

        @Override
        public void serialize(Boolean value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
            String out = "private";
            if (value) {
                out = "public";
            }
            gen.writeString(out);
        }
    }

And here the test: 这里是测试:

public class Test {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Mode mode = new Mode(true);
        String toJson = mapper.writeValueAsString(mode);
        System.out.println(toJson);
    }
}

And as a result I receive: 结果,我收到:

{"public":true,"mode":"public"}

What am I doing wrong? 我究竟做错了什么?

Jackson follows java beans conventions for getter methods. Jackson遵循Java Bean约定的getter方法。

According to these isPublic is a getter for a boolean property named public , different than the isPublic field in Mode . 根据这些, isPublic是名为public的布尔属性的获取器,与ModeisPublic字段不同。 Jackson will serialize that as "public":true . Jackson将序列化为"public":true

In addition to that, you specify a @JsonProperty that Jackson will serialize in a field with the provided name mode . 除此之外,您还指定一个@JsonProperty ,Jackson将在提供的name mode的字段中序列化它。

@JsonDeserialize annotation on the field would have caused Jackson to ignore the getter if the name of the field matched the one implied by the getter method. 如果字段的名称与getter方法隐含的名称匹配,则@JsonDeserialize对该字段的注释将导致Jackson忽略该getter。 The corresponding getter method for a boolean field named isPublic would be isIsPublic() 名为一个布尔字段对应的吸气剂的方法isPublicisIsPublic()

The fact that you specify a Json field name of mode doesn't affect the above. 您指定mode的Json字段名称的事实并不影响上述内容。

Thanks for the detailed answer. 感谢您的详细回答。
You are absolutely right I need to isolate getter Public, and this can do not only with renaming this method, but also using the annotation @JsonIgnore to the method. 完全正确,我需要隔离getter Public,这不仅可以重命名此方法,而且可以对方法使用注释@JsonIgnore。 Like this: 像这样:

class Mode {
    @JsonProperty("mode")
    @JsonSerialize(using = ModeSerializer.class)
    private boolean isPublic;

    public Mode(boolean isPublic) {
        this.isPublic = isPublic;
    }

    @JsonIgnore
    public boolean isPublic() {
        return isPublic;
    }
}

This works for me. 这对我有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM