java 注解禁用_自定义 Jackson 注解与禁用某一特定的注解

一、jackson

jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。最新的版本到2.8,稳定版为2.7

从Jackson 2.0起,核心组件包括:

jackson-annotations(带注释的数据绑定包)。

jackson-core(流式的解析器和生成器)。

jackson-databind(对象映射器,JSON树模型)。

1、java对象转json[json序列化]

看demo

2、json转java类[json反序列化]

看demo

3、json注解

Jackson提供了一系列注解,方便对JSON序列化和反序列化进行控制,下面介绍一些常用的注解。

@JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。

@JsonFormat 此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。

@JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化name,JsonProperty("name")。

@JsonIgnoreProperties({"name","age"}),作用在类上,用来说明属性在序列化和反序列化时需要忽略掉。

@JsonIgnoreProperties(ignoreUnknown=true)也可以注明在反序列化的时候过滤掉未知的属性,防止报错。

@JsonUnwrapped作用在属性上,用来将子Json对象的属性添加到Json对象。

@JsonUnwrapped作用在属性上,2.0+版本中添加了prefix和suffix属性,用在字段添加前后缀。

@JsonNaming作用在类或方法上,作用和JsonProperty名称相同,同时也支持我们自己定制属性命名的策略。

@JsonSerializer(using=MyDateSerializer.class),来指定序列化的实现,一般用于各种自定义的格式转换。

@JsonDeserializer(using=MyDateDeserializer.class),来指定反序列化的实现,一般用于格式的转换。

@JsonPropertyOrder(alphabetic=true,value={"c","b"}),序列化时对属性是否按字母顺序排序,默认不排序,value中的是优先其他排序的属性名称。

。。。。。很多灵活好用的注解,很强大

Jackson 是 Playfrmework 2 中默认的 JSON 处理框架,先前是  GSON,JSON 是 Playframework 中的第一等公民,可见 Jackson 在 Playframewok 中的重要地位。Jackson 提供了一系列的注解可用,像 @JsonIgnore, @JsonProperty, @JsonUnwrapped, @JsonFilter 等。人的需求总是很难得到满足,所以免不了还是要定义自己的注解。比如有这样一个需求,JavaBean 中被 @MaskField(这个即将成为我第一个自定义的注解) 标记的属性或 getter 方法,总是输出为 ******, 无此标记的属性或方法输出原始值。

我尝试过 @JsonFilter  或是单纯的自定义  JsonSerializer, 并不怎么如意。本人最终的实现方式涉及到

@JacksonAnnotationsInside -- 用来创建自己的 @MaskField 注解

JsonSerializer  -- 被 @MaskField 标记的字段采用自定义的 JsonSerializer 来序列化

JacksonAnnotationIntrospector  -- 禁用某一特定的注解,这样可以在做任意时候启用或禁用 @MaskField

再次重复需求,对于下面的 Person 类生成的对象

classPerson {

publicString name = "Yanbin";

publicString getPhone () {

return"(312)666-8888";

}

publicint age = 100;

@JsonProperty("city")

publicString location = "Chicago";

}

想要对于某些用户生成

{"name":"Yanbin","age":"******","city":"Chicago","phone":"******"}

其他用户生成

{"name":"Yanbin","age":100,"city":"Chicago"}

即有条件的隐藏某些敏感信息。

希望自定义 @MaskField 来标 name 属性和 getPhone() 方法。

定义 @MaskField

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.METHOD})

@JacksonAnnotationsInside

@JsonSerialize(using = MaskFieldSerializer.class)

@interfaceMaskField {

}

上面指示了标记为 @MaskField 字段或 getter 方法奖应用  MaskFieldSerializer 为序列化,总是输出为 ******

MaskFieldSerializer 类

classMaskFieldSerializer extendsJsonSerializer {

@Override

publicvoid serialize(Object value, JsonGenerator jgen, SerializerProvider provider)

throwsIOException {

jgen.writeString("******");

}

}

现在把 @MaskField 应用到  Person 类

classPerson {

publicString name = "Yanbin";

@MaskField

publicString phone () {

return"(312)666-8888";

}

@MaskField

publicint age = 100;

@JsonProperty("city")

publicString location = "Chicago";

}

用代码测试一下

ObjectMapper maskMapper = newObjectMapper();

System.out.println(maskMapper.writeValueAsString(newPerson()));

输出结果没错了,就是

{"name":"Yanbin","age":"******","city":"Chicago","phone":"******"}

本文原始链接, 来自 g

凡是标记了 @MaskField 的字段或 getter 方法最终输出统统为 ******, 还记得还有个需求是对于某些时候还希望看到原貌,即{"name":"Yanbin","age":100,"city":"Chicago"}

也就是有时要只禁用 @MaskField 注解。Jackson 可以调用

maskMapper.configure(MapperFeature.USE_ANNOTATIONS, false);

来禁用所有的注解,那么像 @JsonProperty, @JsonIgnore 这样的注解如何是好,肯定不能一棍子打死,所以这里只是需要适时的把  @MaskField 禁用即可。这时候要用到 JacksonAnnotationIntrospector 来选择某个 Annotation 来禁用了。

因而自定义 DisablingMaskFieldIntrospector

classDisablingMaskFieldIntrospector extendsJacksonAnnotationIntrospector {

@Override

publicboolean isAnnotationBundle(Annotation ann) {

if(ann.annotationType().equals(MaskField.class)) {

returnfalse;

}else{

returnsuper.isAnnotationBundle(ann);

}

}

}

如果是 MaskField 就 return false, 禁用  @MaskField 注解

该告诉你的 ObjectMapper 使用这个自定义 AnnotationIntrospector,下面的测试代码

ObjectMapper showAllMapper = newObjectMapper();

showAllMapper.setAnnotationIntrospector(newDisablingMaskFieldIntrospector());

System.out.println(showAllMapper.writeValueAsString(newPerson()));

输出为

{"name":"Yanbin","age":100,"city":"Chicago"}

也就是要不要采用 DisablingMaskFieldIntrospector 就决定了我们禁止还是启用 @MaskField 注解的功能。

浪费点篇幅,上面完整的代码如下

importcom.fasterxml.jackson.annotation.*;

importcom.fasterxml.jackson.core.*;

importcom.fasterxml.jackson.databind.*;

importcom.fasterxml.jackson.databind.annotation.JsonSerialize;

importcom.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

importjava.io.IOException;

importjava.lang.annotation.*;

publicclass TestJacksonAnnotation {

privatestatic ObjectMapper maskMapper = newObjectMapper();

privatestatic ObjectMapper showAllMapper = newObjectMapper() {{

setAnnotationIntrospector(newDisablingMaskFieldIntrospector());

}};

publicstatic void main(String[] args) throwsJsonProcessingException {

System.out.println(maskMapper.writeValueAsString(newPerson()));

System.out.println(showAllMapper.writeValueAsString(newPerson()));

}

}

classPerson {

publicString name = "Yanbin";

@MaskField

publicString phone () {

return"(312)666-8888";

}

@MaskField

publicint age = 100;

@JsonProperty("city")

publicString location = "Chicago";

}

classMaskFieldSerializer extendsJsonSerializer {

@Override

publicvoid serialize(Object value, JsonGenerator jgen, SerializerProvider provider)

throwsIOException {

jgen.writeString("******");

}

}

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.METHOD})

@JacksonAnnotationsInside

@JsonSerialize(using = MaskFieldSerializer.class)

@interfaceMaskField {

}

classDisablingMaskFieldIntrospector extendsJacksonAnnotationIntrospector {

@Override

publicboolean isAnnotationBundle(Annotation ann) {

if(ann.annotationType().equals(MaskField.class)) {

returnfalse;

}else{

returnsuper.isAnnotationBundle(ann);

}

}

}

执行后输出为

{"name":"Yanbin","age":"******","city":"Chicago","phone":"******"}

{"name":"Yanbin","age":100,"city":"Chicago"}

实际的操作就是根据不同的条件使用  maskMapper 或是 showAllMapper 来进行序列化。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值