如何指定杰克逊只使用字段-最好是全局使用


189

默认的jackon行为似乎同时使用属性(getter和setter)和字段来序列化和反序列化为json。

我想将这些字段用作序列化配置的规范来源,因此根本不希望杰克逊查看属性。

我可以使用注解在单个类的基础上执行此操作:

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

但是我不想在每堂课上都讲这个...

是否可以全局配置?喜欢添加一些到对象映射器?


1
蒂姆给出了一个很好的答案。另一种可能性是,如果您有一个通用的基类,则可以在该基类上添加类注释。批注由Jackson继承。
StaxMan 2011年

1
我想我已经尝试过了,但是似乎您必须告诉子类使用基本情况所定义的内容……
Michael Wiles

2
不可以,除非子类覆盖了类注释,否则父对象的注释就好像它们是子类定义的一部分一样可见(如果不是,这将是一个错误)。这不一定是JDK处理注释的方式,但是Jackson会对注释(甚至是方法注释)实现完全继承。
StaxMan

当心INFER_PROPERTY_MUTATORS标志。如果存在可见的吸气剂或吸气剂,它将强制设定者的可见性。
OndraŽižka18年

Answers:


157

您可以这样配置各个ObjectMappers:

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));

如果要全局设置,通常会通过包装器类访问已配置的映射器。


3
很好,尽管我认为您可能还需要设置检查器(withXxx()方法通常会创建一个新对象)。所以像'mapper.setVisibilityChecker(mapper.getVisibilityChecker()。with ...);之类的东西
StaxMan 2011年

@StaxMan很好地调用了setVisibilityChecker,我编辑了答案以反映出来。
Kevin Bowersox

42
withGetterVisibility没有涵盖is*方法,但有withIsGetterVisibility针对他们的方法。
qerub 2012年

13
setVisibilityChecker不推荐使用。使用setVisibility代替。
0x7d7b '16

1
这就是我所需要的!这种配置使我可以使用Mixin轻松地将Hibernate实体转换为DTO。默认情况下,ObjectMapper会序列化所有内容,而Mixin必须指定要忽略的属性(即,用减法代替交集)。
DeliciousWheat19年

150

在Jackson 2.0及更高版本中,您可以简单地使用:

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);

关闭自动检测。


1
大家好,我使用的是Jackson 1.9.0 jar。在将对象序列化为json字符串时,我得到了其他json属性。我需要获取json字符串,该字符串仅包含@JsonProperty提到的变量。你能帮我吗?
jrhamza

7
您可以从OP问题中提到的类注释开始:@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)接下来,必须注释要包含的每个属性@JsonProperty
lukk 2013年

谢谢!以前,我发现了许多代码示例,其中引用了JsonMethod而不是PropertyAccessor。如果搜索JsonMethod,那么很少会获得指向PropertyAccessor的链接,那么...在后继工件中查找替换类名称的最佳方法是什么?可以强悍而讨厌,不是吗?
philburns

38

专门针对boolean is*()吸气剂:

我花了很多时间来解释为什么两个都不行

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

也不是

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

为我的布尔型Getter / Setter工作。

解决方法很简单:

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

更新:spring-boot允许配置它:

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

请参阅通用应用程序属性#JACKSON


1
您能否详细说明将简单的解决方案应用于bean类?
Pavel Niedoba '16

1
谢谢。那是吉特为我节省了一天。
grinch

这不是问题的答案,而是一种误导。
OndraŽižka18年

14

对于杰克逊1.9.10,我使用

ObjectMapper mapper = new ObjectMapper();

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

转到自动检测。


2
就是这样。谢谢。
cuneytykaya 2014年

不知道这样做与禁用“自动检测”之间是否有任何区别。
xenoterracide

10

怎么样:我用了mixin

不符合规定的对象

@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;
}

混合:

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

用法:

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

没有什么可以说您不能讲授任何数量的类并应用相同的mixin的。

如果您不熟悉mixin,则它们在概念上很简单:mixin的结构被强加到目标类上(根据jackson,就JVM而言)。


3

如果您想在全局范围内执行此操作而不必担心您的配置ObjectMapper,则可以创建自己的注释:

@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 {
}

现在,您只需使用注释您的课程,@JsonExplicit就可以开始了!

另外,请确保编辑上面的调用以@JsonAutoDetect确保您将值设置为适合您的程序的值。

感谢https://stackoverflow.com/a/13408807帮助我了解@JacksonAnnotationsInside


3

如果使用Spring Boot,则可以按以下方式全局配置Jackson :

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);
    }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.