导言:
看过前几篇自定义注解文章的同学, 应该能感受到@JsonSerialize 注解的强大, 本篇将介绍另一个对应的注解@JsonDeserializer的强大功能. 这俩注解可以配合着使用, 让你的代码在序列化或反序列化时, 无比的优雅.
场景:
回忆和前端对接口时, 经常会遇到以下这种场景 : 有一组字段,我定义的数据类型是String类型,如果选择了一个,传单个数字;如果多选了,需要用逗号分隔比如1,2,3来传值。但是后来对接的时候,前端那边说,他那边不好处理,多选的,想要传数组。然而,我后边的逻辑都写好了,修改的话,还需要自己手动一个一个的将数组转为逗号分隔的字符串。这样做是可以,但是显得很不优雅。
废话不多说, 上代码:
自定义序列化与反序列化策略类:
/**
* 序列化时 逗号拼接转数组 "0","1","2" -> ["0","1","2"]
*
* @author Lynn
* @date 2022/11/8 14:45
*/
@NoArgsConstructor
public class StringToArraySerializer extends JsonSerializer<String> {
@Override
public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (StringUtils.isNotBlank(str)) {
String[] split = str.split(",");
jsonGenerator.writeArray(split, 0, split.length);
}
}
}
/**
* 反序列化时 将数组转为逗号拼接 ["0","1","2"] -> "0","1","2"
*
* @author Lynn
* @date 2022/11/8 14:36
*/
@NoArgsConstructor
public class ArrayToStringDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
if (treeNode instanceof IntNode) {
return ((IntNode) treeNode).asText();
} else if (treeNode instanceof LongNode) {
return ((LongNode) treeNode).asText();
} else if (treeNode instanceof DoubleNode) {
return ((DoubleNode) treeNode).asText();
} else if (treeNode instanceof ArrayNode) {
//字符串数组,会多出两个引号,需要手动去除
return StringUtils.replace(StringUtils.join((ArrayNode) treeNode, ","), "\"", "");
} else if (treeNode instanceof TextNode) {
return ((TextNode) treeNode).asText();
}
return "";
}
}
自定义数组与逗号拼接字符串自动转化注解:
该注解适用于序列化/反序列化场景, 说人话就是解析前端传参以及接口返回对象时.
/**
* 数组和逗号拼接转换注解
*
* @author Lynn
* @date 2022/11/8 14:11
*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = StringToArraySerializer.class)
@JsonDeserialize(using = ArrayToStringDeserializer.class)
public @interface StringArrayConvert {
}
具体使用:
解析入参: 无论前端传 [“0,1,2”] / “0,1,2” 都会转为 “0,1,2”
/**
* @author Lynn
* @date 2022/8/30 18:35
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ProductGroupAddRequest extends DataBaseRequest {
/**
* app来源
*/
@StringArrayConvert
@NotBlank(message = "展示途经不能为空")
@EnumValid(message = "展示途经输入错误", enumClass = AppSourceEnum.class)
private String appSource;
}
返回出参: 将 “0,1,2” 转化为 [“0,1,2”]
/**
* @author Lynn
* @date 2022/8/30 16:53
*/
@Data
public class ProductGroupTreeResponse {
/**
* app来源
*/
@StringArrayConvert
private String appSource;
}
由此场景可以推广, 但凡前端想要的数据模型和后端定义的不一致, 都可以在序列化与反序列化时, 用自定义序列化类做处理, 这样可以简化业务代码.