Why Jackson maps to private fields when visibility is public only?

14 views
Skip to first unread message

mjuric

unread,
Apr 5, 2020, 11:43:15 AM4/5/20
to jackson-user
I discovered that Jackson under some circumstances would map private fields even though visibility is set to public only. See below very simple convertValue unit test example where I would expect r1 and r2 to have 2 different values, since I assumed that Jackson wouldn't map public getters to their internal private fields when visibility is public only. I found a similar issue with private set methods where it would attempt to create internal deserializers for these setters and in turn cause exceptions when the parameter was not serializable. Sure, I can workaround this using JsonIgnore annotations, but is this really suppose to work like that or is this maybe a bug? I tested this with versions 2.9.8 and 2.10.4. 


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;

import java.util.UUID;

public class JacksonPrivatePropertyAccessTest {

   
public static class RandomId {

       
private String id = UUID.randomUUID().toString();

       
public String getId() {
           
return id;
       
}

   
}

   
@Test
    public void noPrivateAccess() {
       
RandomId r1 = new RandomId();
       
ObjectMapper mapper = new ObjectMapper();
        mapper
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.PUBLIC_ONLY);
       
RandomId r2 = mapper.convertValue(r1, RandomId.class);
       
Assert.assertNotEquals(r1.getId(), r2.getId());
   
}
}


Tatu Saloranta

unread,
Apr 5, 2020, 12:48:35 PM4/5/20
to jackson-user
On Sun, Apr 5, 2020 at 8:43 AM mjuric <mario.j...@gmail.com> wrote:
>
> I discovered that Jackson under some circumstances would map private fields even though visibility is set to public only. See below very simple convertValue unit test example where I would expect r1 and r2 to have 2 different values, since I assumed that Jackson wouldn't map public getters to their internal private fields when visibility is public only. I found a similar issue with private set methods where it would attempt to create internal deserializers for these setters and in turn cause exceptions when the parameter was not serializable. Sure, I can workaround this using JsonIgnore annotations, but is this really suppose to work like that or is this maybe a bug? I tested this with versions 2.9.8 and 2.10.4.

Good question!

This is intentional, controlled by feature:

MapperFeature.INFER_PROPERTY_MUTATORS

which, when enabled (default: true) will "pull in" otherwise
non-visible mutators (setter or field), as long as there is accessor
(visible get method).
If you do not wish this to happen (for example, due to security
reasons), you would want to disable this setting -- or, remove
visibility of getters as well.

I hope this helps,

-+ Tatu +-

mjuric

unread,
Apr 6, 2020, 1:24:03 AM4/6/20
to jackson-user
Thanks, this was really helpful. I always get surprised about the many possible settings that Jackson allows, and this was one of those I never payed any attention to previously.
Reply all
Reply to author
Forward
0 new messages