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

2023年6月19日11:08:57

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

@JsonSerialize常见用法

标注范围:类、属性、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区别与联系作用

@JsonProperty解析

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

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

被序列化后的效果

{"macAmount": "value"}

@JsonIgnore解析

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

@JsonComponent解析

为指定类设置序列化规则,无需其他任何额外配置,即可生效。当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

  • 作者:张子行的博客
  • 原文链接:https://blog.csdn.net/qq_42875345/article/details/113483758
    更新时间:2023年6月19日11:08:57 ,共 4299 字。