瑞瑞哥的博客

FastJson使用Serializer和Deserializer实现枚举类自定义序列化

FastJson使用Serializer和Deserializer实现枚举类自定义序列化

背景

在公司写代码的时候,有些场景必须,或者只能用Fastjson,比如人家封装了一层,或者其他什么场景,这时候可能会想自定义序列化。Fastjson提供了一些能力,可以应对大家的诉求。比如:

  1. 某个属性序列化时候的key,不用变量名而是用别的。

  2. 序列化的时候忽略某个属性,让他不输出。

但是下面这些场景,我们需要用到Fastjson提供的更强大的功能:

  1. 我自己写了个枚举类,但是Fastjson的枚举类默认自定义序列化/反序列化的能力不够,或者能力够了,用起来很麻烦。
  2. 我需要一些很底层,很不套路的序列化能力。比如是个Pojo对象,那么给它序列化的时候,输出的字符串怎么也得套一层花括号{}吧?这时候我不想要花括号,我想直接输出值怎么办?

这时候需要用到自定义的SerializerDeserializer

代码

首先定义一个自己的枚举类,其实你换成Pojo也是一样的。

1
2
3
4
5
6
7
public enum TestEnum {
/**
* Various
*/
TEST("test"),
private String name;
}

自定义的Deserializer

1
2
3
4
5
6
7
8
9
10
11
12
13
@SuppressWarnings("unchecked")
public class TestEnumDeserializer implements ObjectDeserializer {
@Override
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
String testEnumString = parser.parseObject(String.class);
return (T)TestEnum.fromName(testEnumString);
}

@Override
public int getFastMatchToken() {
return 0;
}
}

自定义的Serializer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestEnumSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName,
Type fieldType, int features)
throws IOException {
SerializeWriter out = serializer.getWriter();
if (object == null) {
serializer.getWriter().writeNull();
return;
}

TestEnum testEnum = (TestEnum)object;
out.write(testEnum.getName());
}
}

现在还有个问题,做到这一步,每次序列化/反序列化的时候,需要手动指定 Serializer或者Deserializer。这固然可以,但是如果需要自动的话,就得在程序启动之前,全局注册一下。

也就是将你的自定义类的类型,和你的Serializer以及Deserializer绑定一下,否则Fastjson这个类要用你的自定义序列化策略呢。

如果是SpringBoot应用,建议用@Component注解和PostConstruct注解,轻松完成

1
2
3
4
5
6
7
8
9
@Component
public class FastjsonConfig{
@PostConstruct
public void init(){
SerializeConfig.getGlobalInstance().put(TestEnum.class), new TestEnumSerializer());

ParserConfig.getGlobalInstance().putDeserializer(TestEnum.class), new TestEnumDeserializer());
}
}

参考

Github一篇文章和CSDN一篇文章,具体忘记了。如果侵权请联系。