使用SpringMVC,在Controller中接受请求的数据,或者返回数据,有些需要做些特殊的处理。比如说,请求过来的数据是以万为单位的,但是我们需要转化为以元单位的;返回的手机号,中间四位需要以****隐藏。对于这种需求,我们可以手动进行处理。我们也可用@JsonDeserialize和@JsonSerialize来优雅的处理。
在我做的项目中,遇到这样一种情况,有一组字段,我定义的数据类型是String类型,如果选择了一个,传单个数字;如果多选了,需要用逗号分隔比如1,2,3来传值。但是后来对接的时候,前端那边说,他那边不好处理,多选的,想要传数组。然而,我后边的逻辑都写好了,修改的话,还需要自己手动一个一个的将数组转为逗号分隔的字符串。这样做是可以,但是显得很不优雅。于是我采用了@JsonDeserialize来处理。
首先,需要自定义JsonDeserializer类
public class ParamToStrDeserializer 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 ArrayNode) {
//字符串数组,会多出两个引号,需要手动去除
return StringUtils.replace(StringUtils.join((ArrayNode) treeNode, ","), "\"", "");
} else if (treeNode instanceof TextNode) {
return ((TextNode) treeNode).asText();
}
return "";
}
}
通过ParamToStrDeserializer的转化,无论传的值是数字比如:【1】或者【"1"】;还是数组,比如【[1,2,3]】或者【["1","2","3“]】都能统一转化为用逗号分隔的字符串格式。
然后在需要自动转化的字段上加上注解
@JsonDeserialize(using = ParamToStrDeserializer.class)
private String state;
这样,无论前端传的是哪种格式,state最终都是一种类型了,做到了以不变应万变。
接下来看@JsonSerialize的用法,@JsonDeserialize的反向用法。
public class MyJsonSerializer extends JsonSerializer<List<Integer>> {
@Override
public void serialize(
List<Integer> stateList, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String join = StringUtils.join(stateList, ",");
jsonGenerator.writeString(join);
}
}
@JsonSerialize(using = MyJsonSerializer.class)
private List<Integer> states;
那我们设置的states是个List,但是前端拿到的就是逗号分隔的字符串了。
那这两个有什么区别呢:
@JsonSerialize:json序列化注解,作用于getter()方法,将java对象序列化为json数据。可以理解为用在处理返回的数据上
@JsonDeserialize:json反序列化注解,作用于setter()方法,将json数据反序列化为java对象。可以理解为用在处理接收的数据上。
需要注意的是,这两个注解只在json序列化和反序列化的时候触发,其他时候并不生效!