jackson-databind: @JsonProperty(access = Access.READ_ONLY) - unexpected behaviour

Hey,

I was hoping to make use of @JsonProperty(access = Access.READ_ONLY), but failed.

Assume this class:

public class TestPojo
{
    private String firstName;

    private String lastName;

    @JsonProperty(access = Access.READ_ONLY)
    public String getFullName()
    {
        return firstName + " " + lastName;
    }

    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    public String getLastName()
    {
        return lastName;
    }

    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }
}

I couldn’t find a way to stop the deserializer from attempting to deserialize the field “fullName”. The only thing that helps is to create a setter and annotate it with @JsonIgnore. However, that setter does not make sense and I don’t want to have it. Is this a bug in behaviour or am I missing something? Thanks

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 4
  • Comments: 29 (14 by maintainers)

Commits related to this issue

Most upvoted comments

Hi,

is there some easy workaround, until this is fixed? I mean instead of implementing a noop setter method?

The annotation @JsonIgnoreProperties sounds like it could help here. But it also has no effect, if I add it to a getter, regardless which values I choose for allowGetters or allowSetters.

Update: It seems that I found a solution by adding

@JsonIgnoreProperties(value="some_field", allowGetters = true, allowSetters = false)

to the class. So this could be a solution, if we don’t need the @JsonIgnoreProperties annotation on class level for other purposes.

Also: my earlier explanation was exactly backwards. Javadocs state it correctly (if not well): READ_ONLY refers to POJO being handled in read-only way, and WRITE_ONLY opposite. So Java-centric, not JSON-centric.

I really should have named values differently (GETTER_ONLY, SETTER_ONLY, perhaps).

@cowtowncoder

I think this is still not fixed. I have the same problem with 2.10.3 My getter is annotated with @JsonProperty(value = "t", access = JsonProperty.Access.READ_ONLY) The BeanDeserializerBase tries to deserialize it which results into Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "t"

Here is the stacktrace:

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "t" 
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:843)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1206)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1592)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1570)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:189)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:130)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:193)
    at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:120)
    at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromArray(AsArrayTypeDeserializer.java:53)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:191)
    at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3275)
    at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:150)
    ... 138 more

FYI: _removeUnwantedAccessor is not called at all.

I can reproduce this with 2.6. Looks like READ_ONLY does actually hide/remove setter method (my test fails with “unknown property”), but will not mark it as ignorable, which it probably should do.