236

Default jackon behaviour seems to use both properties (getters and setters) and fields to serialize and deserialize to json.

I would like to use the fields as the canonical source of serialization config and thus don't want jackson to look at properties at all.

I can do this on an individual class basis with the annotation:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

But I don't want to have to put this on every single class...

Is it possible to configure this globally? Like add some to the Object Mapper?

5
  • 1
    Tim gave a good answer. Another possibility is that if you have a common base class, you can put class annotations to that one; annotations are inherited by Jackson.
    – StaxMan
    Commented Aug 18, 2011 at 18:44
  • 1
    I think I tried that, but it seems you have to tell the sub classes to use what the base case defines... Commented Aug 19, 2011 at 8:40
  • 2
    No, unless sub-class overrides class annotation, parent's annotations are visible as if they were part of sub-class definition (if not, this would be a bug). This is not necessarily how JDK deals with annotations, but Jackson implements full inheritance for annotations (even for method annotations).
    – StaxMan
    Commented Aug 19, 2011 at 18:10
  • Beware of the INFER_PROPERTY_MUTATORS flag. It forces the visibility of setters if there is a visible getter or field. Commented Jun 17, 2018 at 23:43
  • And others. Commented Jun 18, 2018 at 2:50

9 Answers 9

198

You can configure individual ObjectMappers like this:

ObjectMapper mapper  = new ObjectMapper();
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

If you want it set globally, I usually access a configured mapper through a wrapper class.

5
  • 4
    Good, although I think you may need to also set the checker (withXxx() methods usually create a new object). So something like 'mapper.setVisibilityChecker(mapper.getVisibilityChecker().with...);'
    – StaxMan
    Commented Aug 18, 2011 at 18:43
  • @StaxMan good call on setVisibilityChecker, I edited the answer to reflect. Commented Sep 29, 2011 at 18:27
  • 57
    withGetterVisibility doesn't cover is* methods, but there's withIsGetterVisibility for them.
    – qerub
    Commented May 12, 2012 at 19:23
  • 15
    setVisibilityCheckeris deprecated. Use setVisibility instead. Commented Apr 6, 2016 at 12:09
  • 1
    This is just what I needed! This configuration allowed me to use a Mixin to easily convert Hibernate entities to DTOs. By default the ObjectMapper serializes everything and a Mixin would have to specify which properties to ignore (i.e. a subtraction instead of an intersection).
    – TastyWheat
    Commented Jun 3, 2019 at 18:00
185

In Jackson 2.0 and later you can simply use:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;   

...

ObjectMapper mapper = new ObjectMapper();    
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

to turn off autodetection.

3
  • 1
    Hi guys, I am using Jackson 1.9.0 jar. I am getting additional json property, while serializing object to json string. I need to get the json string, which contains only mentioned variables with @JsonProperty. Can you please help me on this ?
    – jrh
    Commented Nov 23, 2013 at 22:01
  • 9
    You can start with class annotation mentioned in OP question: @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE) Next, you have to annotate each property you want to include with @JsonProperty
    – lukk
    Commented Nov 25, 2013 at 16:07
  • Thanks! Before, I've found many code examples where JsonMethod was referenced instead of PropertyAccessor. If you search for JsonMethod, you rarely get links to PropertyAccessor then... What is the best way to find replacement class names in successor artifacts? Can be tough and nasty, no?
    – philburns
    Commented Mar 26, 2019 at 15:44
48

Specifically for boolean is*() getters:

I've spend a lot of time on why neither below

  @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

nor this

  setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

worked for my Boolean Getter/Setter.

Solution is simple:

  @JsonAutoDetect(isGetterVisibility = Visibility.NONE, ...          
  setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

UPDATE: spring-boot allowed configure it:

jackson:
  visibility.field: any
  visibility.getter: none
  visibility.setter: none
  visibility.is-getter: none

See Common application properties # JACKSON

3
  • 1
    Could you elaborate how simple solution should be applied to bean class? Commented Mar 18, 2016 at 9:33
  • 1
    Thank you. That isGetter saved the day for me.
    – grinch
    Commented Mar 4, 2017 at 16:47
  • This is not an answer to the question and is rather misleading. Commented Jun 17, 2018 at 23:15
18

for jackson 1.9.10 I use

ObjectMapper mapper = new ObjectMapper();

mapper.setVisibility(JsonMethod.ALL, Visibility.NONE);
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

to turn of auto dedection.

1
  • wonder if there's any difference between doing this and disabling the "auto detects". Commented Jan 27, 2016 at 22:52
10

How about this: I used it with a mixin

non-compliant object

@Entity
@Getter
@NoArgsConstructor
public class Telemetry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pk;
    private String id;
    private String organizationId;
    private String baseType;
    private String name;
    private Double lat;
    private Double lon;
    private Instant updateTimestamp;
}

Mixin:

@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public static class TelemetryMixin {}

Usage:

    ObjectMapper om = objectMapper.addMixIn(Telemetry.class, TelemetryMixin.class);
    Telemetry[] telemetries = om.readValue(someJson, Telemetry[].class);

There is nothing that says you couldn't foreach any number of classes and apply the same mixin.

If you're not familiar with mixins, they are conceptually simply: The structure of the mixin is super imposed on the target class (according to jackson, not as far as the JVM is concerned).

7

If you want a way to do this globally without worrying about the configuration of your ObjectMapper, you can create your own annotation:

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonAutoDetect(
        getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE,
        creatorVisibility = JsonAutoDetect.Visibility.NONE
)
public @interface JsonExplicit {
}

Now you just have to annotate your classes with @JsonExplicit and you're good to go!

Also make sure to edit the above call to @JsonAutoDetect to make sure you have the values set to what works with your program.

Credit to https://stackoverflow.com/a/13408807 for helping me find out about @JacksonAnnotationsInside

7

If you use Spring Boot, you can configure Jackson globally as follows:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY);
    }

}

5

@since 2.10 version we can use JsonMapper.Builder and accepted answer could look like:

JsonMapper mapper = JsonMapper.builder()
    .visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
    .visibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
    .visibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)
    .visibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
    .visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)
.build();
1
  • 1
    +1 – The absolute cleanest way to configure your JsonMapper. Period. May be worth including IS_GETTER here for completeness – although it's not what the OP explicitly asked for, they implicitly want it ;)
    – Philzen
    Commented Jan 8 at 20:23
1

It's very tricky in Kotlin with data classes and is* methods. For example for class:

data class SomeClass(val foo: String, val bar: String, val isSomething: Boolean):Serializable { fun isEmpty() = foo.isEmpty() }

I'm getting json like: {"bar"="bar", "empty"=false, "foo"="foo", "isSomething"=true} And after setting: setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE) the json is: {"bar"="bar", "foo"="foo"}

The only way I found to have isSomething and do not have empty is adding the @JsonIgnore or @JvmSynthetic annotation on isEmpty()

Moreover the fun fact is that adding method like isFoo(): Boolean serializes foo only once, as a String.

Not the answer you're looking for? Browse other questions tagged or ask your own question.