1. 前言
fastjson 是阿里巴巴的开源 JSON 解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为JSON字符串,也可以从 JSON字符串反序列化到 JavaBean。
还有如 Jackson 、Gson 等等 JSON 解析库也很强大。
2. 对 Enum 的特殊处理
2.1 前戏
在我们开发中常常会用到枚举,比如表示会员等级、性别、是否激活等等,本来拿性别来举例,0为女,1为男。
先介绍一下枚举的一个特性 ordinal
,它是一个常量
它记录这枚举常量的序数,从0开始,像数组索引一样,我们可以合理地利用这个特性(虽然很多地方说不推荐用,但是个人觉得是可以合理利用的)
定义一个Sex枚举
1 2 3 4
| public enum Sex { female, male, }
|
那么意味着 female 为0,male 为1 ,这个时候不管前台传值0或者值 female ,我们都知道能解析到 female 这个常量
为0时也能解析到,这里就不演示了。我们可以发现返回的 sex 也是 female ,那如何返回0呢,这个时候我们就需要自定义枚举序列化规则了
2.2 定制序列化规则
1 2 3 4 5 6 7
| public class SexEnumSerializer implements ObjectSerializer { @Override public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { Sex sex = (Sex) object; serializer.out.writeInt(sex.ordinal()); } }
|
实现 fasjson 的 ObjectSerializer 去自定义 Sex 这个枚举的序列化规则,然后在类的属性上使用
当响应时可以看到经过了我们自定义的序列化规则,在这里我们可以获取到响应 json 以及字段名、类型等等信息,我们在这个时候做点手脚就可以返回 ordinal 了
2.3 定制反序列化规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class SexEnumDeSerializer implements ObjectDeserializer {
@Override public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { Object parse = parser.parse(); if (Objects.isNull(parse)){ return (T) Sex.female; } return (T) parse; }
@Override public int getFastMatchToken() { return 0; } }
|
为我们的 Sex 配置反序列化规则
此时 sex 为 null ,在我们反序列化时就会按照我们的规则选择 female ,然后返回时序列化 为 ordianl ,也就是0
3. 配置 HttpMessageConverter
可能有的小伙伴进行上面操作时,达不到预期效果,因为 SpringBoot 默认 JSON 解析库是 Jackson !!(接口为什么返回的是 JSON 这是基础,这里不过多阐述),我们需要去定制 HttpMessageConverter
,我们的请求响应文本都是它处理的,既然默认是 Jackson ,那么我们就改成 Fastjson 不就行了 ,直接上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package cn.this52.fastjsondemo;
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
@Configuration public class BaseWebMvcConfig implements WebMvcConfigurer {
@Bean public HttpMessageConverters fastJsonHttpMessageConverter() { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
SerializerFeature[] serializerFeatures = new SerializerFeature[]{
SerializerFeature.WriteMapNullValue, SerializerFeature.WriteEnumUsingToString,
SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.WriteBigDecimalAsPlain, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat, };
fastJsonConfig.setSerializerFeatures(serializerFeatures); fastJsonConfig.setCharset(StandardCharsets.UTF_8); fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
fastConverter.setFastJsonConfig(fastJsonConfig);
return new HttpMessageConverters(fastConverter); } }
|
具体特性可以去看看文档或者源码
4. 最后
需要注意的是在一个对象中对多个属性使用相同的规则,只会选择第一个。
很多问题都是在实际开发中遇到的问题,需要我们去解决,也就衍生出了各种方案,但我们要知道的是自定义一时爽,维护火葬场,还是得根据具体需要去选择方案吧。
上面的例子很简单,不仅限是枚举,其他任意对象都是可以操作的,可以有更复杂的处理,举一反三有无限种可能!