前言:很多时候,例如前端需要字段user可能只是需要用到user中的userName属性,而后端传过去的却是一整个user对象,这样显然是不行的。那有没有一种技术,可以把后端传给前端的user类型的值改变为userName类型的值呢?@JsonComponent、@JsonInclude、@JsonSerialize可以在序列化的时候动手脚,可以自定义返回给前端的序列化的对象的值。完美解决这个问题。
本文概述
- @JsonSerialize常见用法
- 标注在类上面用法
- 标注在属性、get方法上
- @JsonProperty解析
- @JsonIgnore解析
- @JsonComponent解析
- 注意点
- 代码获取
@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效果
加了@JsonSerialize效果
标注在属性、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
@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尾缀请看下文注意点
注意点
此时下面代码会失效,被序列化器作用的类中的@JsonSerialize配置会失效
- @JsonSerialize标注在类上且指定了序列化器a,序列化器a就不要加@JsonComponent注解。
- 同理序列化器a为类b指定了序列化规则,类b就不要加@JsonSerialize注解指定序列化器
/**
* 使用自定义的序列化规则
*/
@JsonSerialize(using = DateSerializer.class)
private LocalDateTime date;
代码获取
https://github.com/zhangzihang3/-workHarvestCode.git