通过Features配置序列化和反序列化的行为
1. Feature介绍
在fastjson 2.x中,有两个Feature,分别用来配置序列化和反序列化的行为。
- JSONWriter.Feature 配置序列化的行为
- JSONReader.Feature 配置反序列化的行为
2. 在JSON的toJSONString和parse方法中使用Feature
2.1 在JSON的toJSONString方法中使用JSONWriter.Feature
Bean bean = ...;
String json = JSON.toJSONString(bean, JSONWriter.Feature.WriteNulls); // 输出对象中值为null的字段
2.2 在JSON的parse方法中使用JSONReader.Feature
String jsonStr = ...;
Bean bean = JSON.parseObject(jsonStr, Bean.class, JSONReader.Feature.UseBigDecimalForDoubles); // 将小数数值读取为BigDecimal
3. 在JSONField和JSONType上配置features
class Model {
@JSONField(serializeFeatures = JSONWriter.Feature.BrowserCompatible)
public long value;
}
也可以在类级别使用JSONType注解:
@JSONType(serializeFeatures = JSONWriter.Feature.WriteMapNullValue)
public class Model {
public String name;
public int age;
}
4. JSONReader.Feature介绍
JSONReader.Feature | 介绍 |
---|---|
FieldBased | 基于字段反序列化,如果不配置,会默认基于public的field和getter方法序列化。配置后,会基于非static的field(包括private)做反序列化。在fieldbase配置下会更安全 |
IgnoreNoneSerializable | 反序列化忽略非Serializable类型的字段 |
SupportArrayToBean | 支持数组映射到Bean的方式 |
InitStringFieldAsEmpty | 初始化String字段为空字符串"" |
SupportAutoType | 支持自动类型,要读取带"@type"类型信息的JSON数据,需要显式打开SupportAutoType |
SupportSmartMatch | 默认下是camel case精确匹配,打开这个后,能够智能识别camel/upper/pascal/snake/Kebab五种case |
UseNativeObject | 默认是使用JSONObject和JSONArray,配置后会使用LinkedHashMap和ArrayList |
SupportClassForName | 支持类型为Class的字段,使用Class.forName。为了安全这个是默认关闭的 |
IgnoreSetNullValue | 忽略输入为null的字段 |
UseDefaultConstructorAsPossible | 尽可能使用缺省构造函数,在fieldBase打开这个选项没打开的时候,会可能用Unsafe.allocateInstance来实现 |
UseBigDecimalForFloats | 默认配置会使用BigDecimal来parse小数,打开后会使用Float |
UseBigDecimalForDoubles | 默认配置会使用BigDecimal来parse小数,打开后会使用Double |
ErrorOnEnumNotMatch | 默认Enum的name不匹配时会忽略,打开后不匹配会抛异常 |
TrimString | 对读取到的字符串值做trim处理 |
ErrorOnNotSupportAutoType | 遇到AutoType报错(缺省是忽略) |
DuplicateKeyValueAsArray | 重复Key的Value不是替换而是组合成数组 |
AllowUnQuotedFieldNames | 支持不带双引号的字段名 |
NonStringKeyAsString | 非String类型的Key当做String处理 |
Base64StringAsByteArray | 将Base64格式的字符串反序列化为byte[] |
DisableSingleQuote | 不允许在key和value中使用单引号 |
5. JSONWriter.Feature介绍
JSONWriter.Feature | 介绍 |
---|---|
FieldBased | 基于字段序列化,如果不配置,会默认基于public的field和getter方法序列化。配置后,会基于非static的field(包括private)做序列化。 |
IgnoreNoneSerializable | 序列化忽略非Serializable类型的字段 |
BeanToArray | 将对象序列为[101,"XX"]这样的数组格式,这样的格式会更小 |
WriteNulls | 序列化输出空值字段 |
BrowserCompatible | 在大范围超过JavaScript支持的整数,输出为字符串格式 |
NullAsDefaultValue | 将null值输出为缺省值,整数类型的Number输出为0,小数类型的Number输出为0.0,String类型输出为"",Character类型输出为\u0000,数组和Collection类型输出为[],其余类型输出{}。 |
WriteBooleanAsNumber | 将true输出为1,false输出为0 |
WriteNonStringValueAsString | 将非String类型的值输出为String,不包括对象和数据类型 |
WriteClassName | 序列化时输出类型信息 |
NotWriteRootClassName | 打开WriteClassName的同时,不输出根对象的类型信息 |
NotWriteHashMapArrayListClassName | 打开WriteClassName的同时,不输出类型为HashMap/ArrayList类型对象的类型信息,反序列结合UseNativeObject使用,能节省序列化结果的大小 |
NotWriteDefaultValue | 当字段的值为缺省值时,不输出,这个能节省序列化后结果的大小 |
WriteEnumsUsingName | 序列化enum使用name |
WriteEnumUsingToString | 序列化enum使用toString方法 |
IgnoreErrorGetter | 忽略getter方法的错误 |
PrettyFormat | 格式化输出 |
ReferenceDetection | 打开引用检测,这个缺省是关闭的,和fastjson 1.x不一致 |
WriteNameAsSymbol | 将字段名按照symbol输出,这个仅在JSONB下起作用 |
WriteBigDecimalAsPlain | 序列化BigDecimal使用toPlainString,避免科学计数法 |
UseSingleQuotes | 使用单引号 |
MapSortField | 对Map中的KeyValue按照Key做排序后再输出。在有些验签的场景需要使用这个Feature |
WriteNullListAsEmpty | 将List类型字段的空值序列化输出为空数组"[]" |
WriteNullStringAsEmpty | 将String类型字段的空值序列化输出为空字符串"" |
WriteNullNumberAsZero | 将Number类型字段的空值序列化输出为0 |
WriteNullBooleanAsFalse | 将Boolean类型字段的空值序列化输出为false |
NotWriteEmptyArray | 数组类型字段当length为0时不输出 |
WriteNonStringKeyAsString | 将Map中的非String类型的Key当做String类型输出 |
ErrorOnNoneSerializable | 序列化非Serializable对象时报错 |
WritePairAsJavaBean | 将 Apache Commons 包中的Pair对象当做JavaBean序列化 |
BrowserSecure | 浏览器安全,将会’<’ ‘>’ ‘(‘ ‘)’字符做转义输出 |
WriteLongAsString | 将Long序列化为String |
WriteEnumUsingOrdinal | 序列化Enum使用Ordinal,缺省是name |
WriteThrowableClassName | 序列化Throwable时带上类型信息 |
LargeObject | 这个是一个保护措施,是为了防止序列化有循环引用对象消耗过大资源的保护措施。 |
UnquoteFieldName | 不带引号输出Key |
NotWriteSetClassName | 当打开WriteClassName时又不想输出Set的类型信息,使用这个Feature |
NotWriteNumberClassName | 当打开WriteClassName时又不想输出Number的类型信息,比如L/S/B/F/D这种后缀,使用这个Feature |
6. 使用示例
6.1 序列化示例
// 基本使用
User user = new User(\"张三\", 25, null);
String json = JSON.toJSONString(user, JSONWriter.Feature.WriteNulls);
// 多个Feature组合使用
String json2 = JSON.toJSONString(user,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.PrettyFormat);
// 使用BeanToArray特性
String json3 = JSON.toJSONString(user, JSONWriter.Feature.BeanToArray);
6.2 反序列化示例
// 基本使用
String json = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":25}\";
User user = JSON.parseObject(json, User.class, JSONReader.Feature.SupportSmartMatch);
// 多个Feature组合使用
User user2 = JSON.parseObject(json, User.class,
JSONReader.Feature.SupportSmartMatch,
JSONReader.Feature.InitStringFieldAsEmpty);
7. 最佳实践建议
- 安全性考虑:
- 默认情况下不要开启
SupportAutoType
,除非确实需要处理带类型信息的JSON - 对于不受信任的数据源,谨慎使用
FieldBased
特性
- 默认情况下不要开启
- 性能优化:
- 对于大数据量的序列化,可以考虑使用
BeanToArray
特性来减小JSON体积 - 在需要保持字段顺序的场景下,使用
MapSortField
特性
- 对于大数据量的序列化,可以考虑使用
- 兼容性处理:
- 在Web前端场景中,使用
BrowserCompatible
来处理大整数 - 对于需要严格数据格式的场景,开启
ErrorOnEnumNotMatch
来及时发现枚举不匹配问题
- 在Web前端场景中,使用
- 空值处理:
- 根据业务需求选择合适的空值处理策略,如
WriteNulls
、WriteNullStringAsEmpty
等
- 根据业务需求选择合适的空值处理策略,如