Jackson: the final field written after being set by @JsonCreator?

It seems that Jackson is using reflection to write additional attributes directly to the fields, even if a constructor was used @JsonCreator

and the field is marked as final

.

Example:

public class Test {
    static class X {
        final String s;

        @JsonCreator
        public X(@JsonProperty("a") String a) {
            s = "s";
        }

        public String getS() {
            return s;
        }
    }

    @org.junit.Test
    public void ds() throws Exception {
        ObjectMapper om = new ObjectMapper();
        X x = om.readValue("{`a`:``, `s`: `t`}".replace('`', '"'), X.class);
        assertEquals("s", x.s);
    }
}

      

The assertion will fail with org.junit.ComparisonFailure: expected:<[s]> but was:<[t]>

.

Is this behavior documented anywhere? Should I turn this off globally at all?

Also, I think this is a very dangerous design: if there is some value that should be read-only to the client, it actually allows the client to set them even if the class is well designed to fit with normal immutable classes.

+3


source to share


1 answer


First: yes, Jackson allows you to deserialize all visible ones, not just those for which the property exists @JsonCreator

. Thus, it is possible to set a smaller set of properties through the constructor and others through setters or fields. This may be required for some cases, such as looping types.

How to prevent use s

for deserialization here. The obvious way is to add @JsonIgnore

for the field, although you will also need @JsonProperty

to for getS()

that to avoid removing them.

But there are other settings, in MapperFeature

.



  • ALLOW_FINAL_FIELDS_AS_MUTATORS

    : if you disable this, the fields final

    will never be used directly for deserialization
  • INFER_PROPERTY_MUTATORS

    : if you disable this, then neither fields nor setters will be "pulled in" in cases where they are not visible otherwise (for fields, public

    you need to be visible, for setters, even private

    good)

So you can turn off one or both settings.

+4


source