序列化之@JsonComponent、@JsonInclude、@JsonSerialize、@JsonIgnore、JsonProperty区别与联系作用

前言:很多时候,例如前端需要字段user可能只是需要用到user中的userName属性,而后端传过去的却是一整个user对象,这样显然是不行的。那有没有一种技术,可以把后端传给前端的user类型的值改变为userName类型的值呢?@JsonComponent、@JsonInclude、@JsonSerialize可以在序列化的时候动手脚,可以自定义返回给前端的序列化的对象的值。完美解决这个问题。

本文概述

  • @JsonSerialize常见用法
    • 标注在类上面用法
    • 标注在属性、get方法上
  • @JsonProperty解析
  • @JsonIgnore解析
  • @JsonComponent解析
    • 注意点
  • 代码获取

标注范围:类、属性、get方法
标注在类上面:指定类的序列化规则
标注在属性、get方法上面:指定属性的序列化规则

标注在类上面用法

这里使用了lombok插件省略了写法。伪代码模拟异常基类

@Data @Builder @AllArgsConstructor @NoArgsConstructor public class BaseException {     private ErrorMsg errorMsg;     private LocalDateTime date; } 

模拟自定义异常的这个场景,@JsonSerialize指定序列化规则,用我们自己定义的序列化器

@JsonSerialize(using = DivSerializer.class) public class DivException extends BaseException {     public DivException(ErrorMsg errorMsg, LocalDateTime date) {         super(errorMsg, date);     } } 

自定义序列化器,此处设置的值也就是前端能够接收到的值(没有设置的属性也就自然没有咯),干涉ErrorMsg = ErrorMsg.code

/**  * @author 张子行  * @class  */ public class DivSerializer extends StdSerializer<DivException> {     /**      * @method 固定代码,原理搞不清      */     protected DivSerializer() {         super(DivException.class);     }     /**      * @method      * @param DivException e:干涉前的对象      * @param JsonGenerator jsonGenerator: json生成器,指定干涉后的json对象                          */     @Override     public void serialize(DivException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {         jsonGenerator.writeStartObject();         jsonGenerator.writeObjectField("date", e.getDate());         jsonGenerator.writeObjectField("ErrorMsg", e.getErrorMsg().getMsg());         jsonGenerator.writeEndObject();     } 

测试代码注意加了@RestController返回值会经过json序列化

/** * @author 张子行 * @class */ @RestController public class GoodsController {  @GetMapping("/testMoney")  public money test() {      money money = new money(100, LocalDateTime.now(), null, "zzh");      return money;  }   @GetMapping("/testDivException")  public DivException b() {      DivException divException = new DivException(new ErrorMsg(100, "error"), LocalDateTime.now());      return divException;  } } 

不加@JsonSerialize效果
序列化之@JsonComponent、@JsonInclude、@JsonSerialize、@JsonIgnore、JsonProperty区别与联系作用
加了@JsonSerialize效果
序列化之@JsonComponent、@JsonInclude、@JsonSerialize、@JsonIgnore、JsonProperty区别与联系作用

标注在属性、get方法上

money类

/**  * @author 张子行  * @class  */  /**  * 类中有字段为null时不返回给前端  */ @JsonInclude(value = JsonInclude.Include.NON_NULL) @Data @AllArgsConstructor public class money {      /**      * 只能被序列化,序列化的key为macAmount      */     @JsonProperty(value = "macAmount", access = JsonProperty.Access.READ_ONLY)     private int amount;     /**      * 使用自定义的序列化规则      */     @JsonSerialize(using = DateSerializer.class)     private LocalDateTime date;     /**      * 为空时不会返回给前端      */     @JsonInclude(value = JsonInclude.Include.NON_EMPTY)     private String unit;     /**      * 序列化不返回给前端的字段      */     @JsonIgnore     private String name; } 

date序列化器

public class DateSerializer extends StdSerializer<LocalDateTime> {     public DateSerializer() {         super(LocalDateTime.class);     }      @Override     public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {         jsonGenerator.writeObject(localDateTime+"ggg");     } } 

测试

/**  * @author 张子行  * @class  */ @RestController public class GoodsController {     @GetMapping("/testMoney")     public money test() {         money money = new money(100, LocalDateTime.now(), null, "zzh");         return money;     }      @GetMapping("/testDivException")     public DivException b() {         DivException divException = new DivException(new ErrorMsg(100, "error"), LocalDateTime.now());         return divException;     } } 

效果
name字段加了@JsonIgnore,所以不会被序列化
unit字段在@JsonInclude作用下,无论是空串还是null都不会被序列化
date字段在@JsonSerialize指定了序列化器下,输出的是时间+ggg
序列化之@JsonComponent、@JsonInclude、@JsonSerialize、@JsonIgnore、JsonProperty区别与联系作用

access = JsonProperty.Access.READ_ONLY,表示只能被序列化

/**  * 只能被序列化  */  @JsonProperty(value = "macAmount", access = JsonProperty.Access.READ_ONLY)  private int amount; 

被序列化后的效果

{"macAmount": "value"} 

被@JsonIgnore标注的属性序列化的时候会被忽略。不序列此字段,效果图同上

为指定类设置序列化规则,无需其他任何额外配置,即可生效。当controller层中的返回值中包含money对象,那么就会被此序列化器作用

/**  * @author 张子行  * @class  */ @JsonComponent public class moneySerializer extends StdSerializer<money> {     protected moneySerializer() {         super(money.class);     }      /**      * 序列化逻辑,只取出Money中的amount      */     @Override     public void serialize(money money, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {         jsonGenerator.writeStartObject();         System.out.println(money);         jsonGenerator.writeObjectField("amount", money.getAmount());         jsonGenerator.writeObjectField("date", money.getDate());         jsonGenerator.writeObjectField("unit", money.getUnit());         jsonGenerator.writeObjectField("name", money.getName());         jsonGenerator.writeEndObject();     } } 

效果图,controller层同上。
unit为null是因为unit加了注解@JsonIgnore
date没有ggg尾缀请看下文注意点
序列化之@JsonComponent、@JsonInclude、@JsonSerialize、@JsonIgnore、JsonProperty区别与联系作用

注意点

此时下面代码会失效,被序列化器作用的类中的@JsonSerialize配置会失效

  • @JsonSerialize标注在类上且指定了序列化器a,序列化器a就不要加@JsonComponent注解。
  • 同理序列化器a为类b指定了序列化规则,类b就不要加@JsonSerialize注解指定序列化器
/**      * 使用自定义的序列化规则      */     @JsonSerialize(using = DateSerializer.class)     private LocalDateTime date; 

https://github.com/zhangzihang3/-workHarvestCode.git