fastjson提供了一个全局的修改序列化配置的方式。如果你对某个类型的默认序列化方式不满意,或者想指定自定义类型的序列化方式,那么你可以通过修改全局配置的方式实现。
修改序列化方式
修改已有类型的序列化方式
例如,你可以通过下面的方式修改 double 类型的序列化方式
1 2
| SerializeConfig config = SerializeConfig.getGlobalInstance(); config.put(Double.class, new DoubleSerializer("#.##"));
|
这样,当你使用 JSON.toJSONString
序列化 double 类型的数据时,结果只会保留两位小数
1 2 3 4 5
| double cost = 16.232342143124d; System.out.println(JSON.toJSONString(cost));
|
指定自定义类型的序列化方式
另外一种情况是自定义类型,例如下面的类型
1 2 3 4 5 6 7 8 9 10 11
| public static class Result { public ResultCode code; }
public static enum ResultCode { LOGIN_FAILURE(8), INVALID_ARGUMENT(0), SIGN_ERROR(17); public final int value; ResultCode(int value){ this.value = value; } }
|
我们可以通过定义 ResultCode
对应的序列化方式,使得输出结果是 int 类型的 value 值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static class ResultCodeSerilaizer implements ObjectSerializer { public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { serializer.write(((ResultCode) object).value); } }
SerializeConfig.getGlobalInstance().put(ResultCode.class, new ResultCodeSerilaizer());
|
这样 JSON.toJSONString()
会使用 ResultCodeSerilaizer
序列化 ResultCode
类型
1 2 3 4 5 6 7
| Result result = new Result(); result.code = ResultCode.SIGN_ERROR;
String json = JSON.toJSONString(result);
Assert.assertEquals("{\"code\":17}", json);
|
一些建议
虽然通过上面的方式修改序列化方式很方便,但是在使用时还是要多加小心
不建议修改默认类型的序列化方式
修改默认类型的序列化方式,可能会产生一些意料之外的问题。例如,程序中可能已经存在很多使用 JSON.toJSONString
序列化的场景,指不定某些场景就依赖默认的序列化格式。在修改了默认类型的序列化方式后,有可能会导致这部分场景的逻辑不符合预期,更重要的是,通常情况下这种问题很难排查。我们最近就遇到了一次类似问题,花了好几个小时才定位到原因。因此,不建议修改默认类型的序列化方式。
如果是新增的自定义类型,只是用作内部使用,增加自定义的序列化方式倒不会有什么影响。但如果是要提供给外部使用,还是保持原样的好。
如何排查
如果真的遇到了序列化的问题,假如说怀疑是某个类型的序列化方式被修改了,那么可以通过 debug 的方式进行验证。在 debug 时,需要将断点打在修改的入口,即 SerializeConfig
的 put
方法处,找到调用栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public boolean put(Type type, ObjectSerializer value) { Type mixin = JSON.getMixInAnnotations(type); if (mixin != null) { IdentityHashMap<Type, ObjectSerializer> mixInClasses = this.mixInSerializers.get(type); if (mixInClasses == null) { mixInClasses = new IdentityHashMap<Type, ObjectSerializer>(4); mixInSerializers.put(type, mixInClasses); } return mixInClasses.put(mixin, value); } return this.serializers.put(type, value); }
|