前言:很多时候,例如前端需要字段user可能只是需要用到user中的userName属性,而后端传过去的却是一整个user对象,这样显然是不行的。那有没有一种技术,可以把后端传给前端的user类型的值改变为userName类型的值呢?@JsonComponent、@JsonInclude、@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效果
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
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尾缀请看下文注意点
此时下面代码会失效,被序列化器作用的类中的@JsonSerialize配置会失效
/** * 使用自定义的序列化规则 */ @JsonSerialize(using = DateSerializer.class) private LocalDateTime date;
https://github.com/zhangzihang3/-workHarvestCode.git