jackson注解

1 @JsonIgnoreType
  • 范围:序列化/反序列化
  • 作用:标注在类上,表示本类不参与序列化
@JsonIgnoreType
public class Dog {
    private String name;
}

public class Person {
    private String name;
    private Dog dog;
}
  • 序列化案例
JsonMapper mapper = new JsonMapper();
Dog dog = new Dog();
dog.setName("狗");
Person person = new Person();
person.setName("人");
person.setDog(dog);
System.out.println(mapper.writeValueAsString(person));//{"name":"人"}
  • 反序列化案例
JsonMapper mapper = new JsonMapper();
String s = "{\"name\":\"人\",\"dog\":{\"name\":\"狗\"}}";
Person person = mapper.readValue(s, Person.class);
System.out.println(person);//Person(name=人, dog=null)

注意反序列化或者序列化时Dog类型必须作为领一个类的属性,否则@JsonIgnoreType无效,如下

JsonMapper mapper = new JsonMapper();

Dog dog = new Dog();
dog.setName("狗");
System.out.println(mapper.writeValueAsString(dog)); //{"name":"狗"}

String string = "{\"name\":\"狗\"}";
System.out.println(mapper.readValue(string,Dog.class));//Dog(name=狗)
2 @JsonIgnore
  • 范围:序列化/反序列化
  • 作用:用来忽略某些字段,可以用在字段、方法上。这个注解一般用在我们要忽略的字段上,序列化/反序列化都有效
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
@JsonIgnoreType
public class Dog {
    @JsonIgnore
    private String name;
    private Integer age;
}
  • 序列化案例
JsonMapper mapper = new JsonMapper();
Dog dog = new Dog();
dog.setName("狗");
dog.setAge(2);
System.out.println(mapper.writeValueAsString(dog));//{"age":2}
  • 反序列化案例
JsonMapper mapper = new JsonMapper();
System.out.println(mapper.readValue("{\"name\":\"狗\",\"age\":2}",Dog.class));//Dog(name=null, age=2)
3 @JsonView
  • 范围:序列化
  • 作用:控制视图输出

用来指定哪些属性可以被包含在JSON视图中。@JsonIgnore和@JsonIgnoreProperties可以排除掉不需要序列化的属性,可是如果一个POJO中有上百个属性如订单类,此时若使用@JsonIgnore书写上就非常麻烦了,这时你就可以使用@JsonView。

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public static class TestPOJO {
    // 视图A
    @JsonView(FilterView.OutputA.class)
    private String a;
    private String c;
    // 视图B
    @JsonView(FilterView.OutputB.class)
    private String d;
    @JsonView(FilterView.OutputB.class)
    private String b;
}


// 控制视图输出
private interface FilterView {
    interface OutputA { }
    interface OutputB { }
}
@Test
public void fun3() throws Exception {
    JsonMapper jsonMapper = new JsonMapper();
    TestPOJO testPOJO = new TestPOJO();
    testPOJO.setA("1");
    testPOJO.setB("2");
    testPOJO.setC("3");
    testPOJO.setD("4");

    // jsonMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
    String jsonStr = jsonMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO);
    System.out.println("视图A:" + jsonStr);
    String jsonStr2 = jsonMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO);
    System.out.println("视图B:" + jsonStr2);
}

运行程序输出:

视图A{"a":"1","c":"3"}
视图B{"c":"3","d":"4","b":"2"}
  • 从结果总可总结出如下使用注意事项:
    1、必须调用writerWithView()方法才能使得视图生效
    2、没有标注@JsonView的属性始终会被写出(对于那种每种视图都有的属性,不标注此注解便可)
    3、控制此行为的特征是:MapperFeature.DEFAULT_VIEW_INCLUSION
    4、开启:输出没有@JsonView注解的属性
    5、关闭:输出有@JsonView注解的属性(默认值,强烈不建议更改它的默认行为
4 @JsonProperty
  • 范围:序列化和反序列化化
  • 作用:定义属性别名和把属性公开

反序列化:把属性公开(反序列化时是根据setXX方法的名字进行反序列化赋值,除非属性是public的,所以@JsonProperty把属性公开)
序列化:把属性公开(序列化时是根据getXX方法的名字进行反序列化赋值,除非属性是public的,所以@JsonProperty可以把属性公开)

@ToString
public class Person {
    //@JsonProperty
    private Integer temAge;
    private String name;
    public void setName(String name) {
        this.name = name;
    }
}
JsonMapper jsonMapper = new JsonMapper();
String jsonStr = "{\"name\":\"赵三\",\"temAge\":1}";
System.out.println( jsonMapper.readValue(jsonStr,Person.class));

没有标注@JsonProperty,运行报错,,因为属性是私有的访问不到
标注@JsonProperty,运行输出:Person(temAge=1, name=赵三)

class Person {
    @JsonProperty("localDate")
    private Date date;
    public Date getDateDiy() {
        return date;
    }
}

最终序列化的结果是(两个属性):{"dateDiy":1576396658760,"localDate":1576396658760},可以想想为什么?

5 @JsonEnumDefaultValue

标注在enum里面的值上作为反序列化时默认值。

该注解仅在开启了DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE才有效
而默认是没有开启的,生产环境建议可以开启。

public enum MyEnum {
    @JsonEnumDefaultValue
    NAME,
    SSS;
}
JsonMapper jsonMapper = new JsonMapper();
jsonMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE );
String jsonStr = "{\"name\":\"null\"}";
//String jsonStr = "{\"name\":\" \"}";
System.out.println( jsonMapper.readValue(jsonStr,Person.class));

null运行输出:Person(name=NAME)
注意:null和空字符串都取默认值

6 @JsonRawValue
  • 范围:序列化
  • 作用:按原样序列化属性。该值不转义或引用。这在已经JSON中序列化的值或已引用值的情况下很有用
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class Person {
    //@JsonRawValue
    private String name;

}
JsonMapper mapper = new JsonMapper();
Person person = new Person("{\"myKey\": 2019}");
System.out.println(mapper.writeValueAsString(person));

运行输出:{“name”:“{“myKey”: 2019}”}
在name属性上加上注解@JsonRawValue,运行输出:{“name”:{“myKey”: 2019}}

7 @JsonUnwrapped
  • 范围:序列化
  • 作用:简单的说就是把你具有层级结构的JSON数据给解包打平了,它还可以指定前缀后缀
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class Person {

    private String name;

    @JsonUnwrapped(prefix = "dog_")
    private Dog dog;
}
JsonMapper jsonMapper = new JsonMapper();
Dog dog = new Dog("小灰狗");
Person person = new Person("张三",dog);
System.out.println( jsonMapper.writeValueAsString(person));

输出:{"name":"张三","dog":{"name":"小灰狗"}}
加上注解输出:{"name":"张三","dog_name":"小灰狗"}

8 @JsonValue
  • 范围:序列化
  • 作用:它能标注在get方法或者字段上,一个类只能用一个。当加上@JsonValue注解时,序列化时就只返回这一个字段的值(直接返回值,而不是json格式了)
public class Dog {
    @JsonValue
    private String name;
    private Integer age;
}

输出就只是name的值 ,而不再是一个JSON串了。

JsonMapper mapper = new JsonMapper();
Dog dog = new Dog();
dog.setName("狗");
dog.setAge(2);
System.out.println(mapper.writeValueAsString(dog)); //"狗"

那@JsonValue具体有何用呢???

举个例子:我们经常使用枚举,它序列化时候使用的是name属性,而我们很多时候希望它序列化为我们自定义的id,肿么办???

class Person {
    private String name;
    private Deleted deleted;
}
@Getter
@AllArgsConstructor
public enum Deleted  {

    FALSE(0, "未删除"), //
    TRUE(1, "已删除"); //

    private int code;
    private String displayName;
}

这个时候我们mapper.writeValueAsString(person)得到的值是:{"name":"小王","deleted":"FALSE"}
大多数时候其实我们并不想暴露一些细节(比如此的true其实就过于细节),而是使用毫无意义的1来代替它。那么我们就可以这么做:

不需要深入到每个注解,在接口处统一使用@JsonValue标注对应方法即可

public interface EnumIntSpecs<E extends Enum<E>> {
    @JsonValue
    int getCode();
    String getDisplayName();
}
@Getter
@AllArgsConstructor
public enum Deleted implements EnumIntSpecs<Deleted> {

    FALSE(0, "未删除"), //
    TRUE(1, "已删除"); //

    private int code;
    private String displayName;
}

这时再执行测试程序,结果为:{"name":"小王","deleted":0}

那反序列化呢,mapper.readValue(" {\"name\":\"小王\",\"deleted\":0}", Person.class);,其返回值如下
在这里插入图片描述
这说明@JsonValue对序列化和反序列化都有效

9 @JsonFormat
  • 范围:序列化和反序列化
// 它可以标注在几乎任何地方(用得最多的是标注在字段上)}) 
public @interface JsonFormat {
	// 指定格式模版。 -> 该模版由具体的序列化器去实现
	public String pattern() default "";
	// 序列化后的类型
	// ANY:并不指定特定的类型(注意和NATURAL的区别)
	// NATURAL:JSON->String  JSON Number -> Java Numbers等等
	// SCALAR:不应该是结构化的数组、对象等。但可以是其它任何类型
	// ARRAY:数组
	// OBJECT:对象
	// NUMBER:数字
	// ... // 省略其它类型如int、string等等
	public Shape shape() default Shape.ANY;
	// 默认值是java.util.Locale#getDefault()
	public String locale() default DEFAULT_LOCALE;
	// 默认时区:GMT  (在中国:如果你格式化的是时间这个必须设置为timezone = "GMT+8",注意timezone = "UTC+8"是不好使的)
	// 当然一般建议通过ObjectMapper进行全局设置
	public String timezone() default DEFAULT_TIMEZONE;

	// 可以单独为这个字段开启or关闭某项特征。比如WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS等等特征
	public JsonFormat.Feature[] with() default { };
	public JsonFormat.Feature[] without() default { };
}
public class Dog {
    private String name;
    // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date date;
}
  • 序列化
JsonMapper mapper = new JsonMapper();
Dog dog = new Dog();
dog.setName("狗");
dog.setDate(new Date());
System.out.println(mapper.writeValueAsString(dog));//{"name":"狗","date":1615710385611}

启用@JsonFormat注解,再次运行测试程序输出为:{"name":"狗","date":"2021-03-14 16:28:01"}

  • 反序列化
JsonMapper mapper = new JsonMapper();
System.out.println(mapper.readValue(" {\"name\":\"狗\",\"date\":\"2021-03-14 16:28:01\"}",Dog.class));

不开启@JsonFormat注解:报错
开启@JsonFormat注解:Dog(name=狗, date=Sun Mar 14 16:28:01 CST 2021)

10 @JsonSerialize / @JsonDeserialize

这两个注解是开发中经常用到的:为某个类、Filed等指定使用专用的序列化器/反序列化器(一般在自定义序列化器时用得多)。形如这样:

@JsonDeserialize(using= DateJsonDeserializer.class)
@JsonSerialize(using= DateJsonSerializer.class)
private Date time;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值