作者:larva-zhh\
起源:www.cnblogs.com/larva-zhh/p/11544317.html
为什么要替换fastjson
工程里大量应用了fastjson作为序列化和反序列化框架,甚至ORM在解决局部字段也依赖fastjson进行序列化和反序列化。那么作为大量应用的根底框架,为什么还要进行替换呢?
起因有以下几点:
- fastjson太过于偏重性能,对于局部高级个性反对不够,而且局部自定义个性齐全偏离了json和js标准导致和其余框架不兼容;
- fastjson文档缺失较多,局部Feature甚至没有文档,而且代码短少正文较为艰涩;
- fastjson的CVE bug监测较弱,很多CVE数据库网站上无关fastjson的CVE寥寥无几,例如近期的AutoType导致的高危破绽,尽管和Jackson的PolymorphicDeserialization是同样的bug,然而CVE网站上简直没有fastjson的bug报告。
框架选型
参考mvnrepository json libraries,依据风行度排序后前十名框架:
- jackson2(com.fasterxml.jackson)
- gson
- org.json
- jackson1(com.codehuas.jackson)
- fastjson
- cheshire
- json-simple
jackson1是曾经过期的框架,因而能够疏忽,cheshire和json-simple排名尚且不如fastjson,也疏忽,残余jackson2、gson以及org.json,其中org.json的使用量(usage)远小于jackson2(不便起见,下文均以jackson均指代jackson2)和gson,因而org.json也能够排除了。
对于jackson和gson的比拟文章有很多,stackoverflow上自行搜寻,上面仅举荐几篇blog:
- jackson vs gson
- JSON in Java
- the ultimate json library json-simple vs gson vs jackson vs json
在性能个性反对、稳定性、可扩展性、易用性以及社区活跃度上 jackson 和 gson 差不多,入门教程能够别离参考baeldung jackson系列 以及 baeldung gson系列。然而jackson有更多现成的类库兼容反对例如jackson-datatype-commons-lang3
,以及更丰盛的输入数据格式反对例如jackson-dataformat-yaml
,而且spring框架默认应用jackson,因而最终我抉择应用jackson。
PS: Jackson 2.10.0开始尝试基于新的API应用白名单机制来防止RCE破绽,详见https://github.com/FasterXML/…,成果尚待察看。
替换fastjson
fastjson常见的应用场景就是序列化和反序列化,偶然会有JSONObject
和JSONArray
实例的相干操作。
以下步骤的源码剖析基于以下版本:
fastjson v1.2.60
jackson-core v2.9.9
jackson-annotations v2.9.0
jackson-databind v2.9.9.3
Deserialization
fastjson将json字符串反序列化成Java Bean通常应用com.alibaba.fastjson.JSON
的静态方法(JSONObject
和JSONArray
的静态方法也是来自于JSON
),罕用的有以下几个API:
public static JSONObject parseObject(String text); public static JSONObject parseObject(String text, Feature... features); public static <T> T parseObject(String text, Class<T> clazz); public static <T> T parseObject(String text, Class<T> clazz, Feature... features); public static <T> T parseObject(String text, TypeReference<T> type, Feature... features); public static JSONArray parseArray(String text); public static <T> List<T> parseArray(String text, Class<T> clazz);
从办法入参就能猜到,fastjson在执行反序列化时的Parse行为由com.alibaba.fastjson.parser.Feature
指定。钻研parseObject
的源码后,发现底层最终都是应用的以下办法:
public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features) { if (input == null) { return null; } // featureValues作为基准解析个性开关值 // 入参features和featureValues取并集失去最终的解析个性 if (features != null) { for (Feature feature : features) { featureValues |= feature.mask; } } DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues); if (processor != null) { if (processor instanceof ExtraTypeProvider) { parser.getExtraTypeProviders().add((ExtraTypeProvider) processor); } if (processor instanceof ExtraProcessor) { parser.getExtraProcessors().add((ExtraProcessor) processor); } if (processor instanceof FieldTypeResolver) { parser.setFieldTypeResolver((FieldTypeResolver) processor); } } T value = (T) parser.parseObject(clazz, null); parser.handleResovleTask(value); parser.close(); return (T) value; }
通过IDE搜寻usage后,发现当没有作为基准解析个性开关的featureValues
入参时,都是应用的DEFAULT_PARSE_FEATURE
作为基准解析个性开关,以下是JSON.DEFAULT_PARSE_FEATURE
的实例化代码:
static { int features = 0; features |= Feature.AutoCloseSource.getMask(); features |= Feature.InternFieldNames.getMask(); features |= Feature.UseBigDecimal.getMask(); features |= Feature.AllowUnQuotedFieldNames.getMask(); features |= Feature.AllowSingleQuotes.getMask(); features |= Feature.AllowArbitraryCommas.getMask(); features |= Feature.SortFeidFastMatch.getMask(); features |= Feature.IgnoreNotMatch.getMask(); DEFAULT_PARSER_FEATURE = features; }
fastjson还会从环境变量中读取配置来批改DEFAULT_PARSER_FEATURE
(尽管很少会有人这么做),但最好还是通过理论运行一下程序来确认你的环境中的理论解析个性开关。
@Test public void printFastJsonDefaultParserFeature() { for (Feature feature : Feature.values()) { if (Feature.isEnabled(JSON.DEFAULT_PARSER_FEATURE, feature)) { System.out.println(feature); } } }
fastjson 和 jackson的反序列化个性对照表
fastjson个性阐明 | fastjson枚举 | fastjson默认状态 | jackson枚举 | jackson默认状态 | jackson个性阐明 |
---|---|---|---|---|---|
Parser close时主动敞开为创立Parser实例而创立的底层InputStream以及Reader等输出流 | Feature.AutoCloseSource | 开启 | JsonParser.Feature.AUTO_CLOSE_SOURCE | 开启 | 放弃开启 |
容许json字符串中带正文 | Feature.AllowComment | 敞开 | JsonParser.Feature.ALLOW_COMMENTS | 敞开 | 依据零碎的json数据状况开启 |
容许json字段名不被引号包含起来 | Feature.AllowUnQuotedFieldNames | 开启 | JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES | 敞开 | 依据零碎的json数据状况开启 |
容许json字段名应用单引号包含起来 | Feature.AllowSingleQuotes | 开启 | JsonParser.Feature.ALLOW_SINGLE_QUOTES | 敞开 | 依据零碎的json数据状况开启 |
将json字段名作为字面量缓存起来,即fieldName.intern() |
Feature.InternFieldNames | 开启 | – | – | jackson默认应用InternCache 缓存了PropertyName |
辨认ISO8601格局的日期字符串,例如:2018-05-31T19:13:42.000Z 或2018-05-31T19:13:42.000+07:00 |
Feature.AllowISO8601DateFormat | 敞开 | – | – | jackson默认反对ISO8601格局日期字符串的解析,并且也能够通过ObjectMapper.setDateFormat 指定解析格局 |
疏忽json中蕴含的间断的多个逗号,非标准个性 | Feature.AllowArbitraryCommas | 敞开 | – | – | jackson不反对该个性,且该个性是非规范个性,因而能够疏忽 |
将json中的浮点数解析成BigDecimal对象,禁用后会解析成Double对象 | Feature.UseBigDecimal | 开启 | DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS | 敞开 | 倡议开启 |
解析时疏忽未知的字段持续实现解析 | Feature.IgnoreNotMatch | 开启 | DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES | 开启 | jackson默认开启遇到未知属性须要抛异样,因而如要和fastjson保持一致则须要敞开该个性 |
如果你用fastjson序列化的文本,输入的后果是依照fieldName排序输入的,parser时也能利用这个程序进行优化读取。这种状况下,parser可能取得十分好的性能 | Feature.SortFeidFastMatch | 敞开 | – | – | fastjson外部解决逻辑,jackson不反对该个性,不影响性能 |
禁用ASM | Feature.DisableASM | 敞开 | – | – | fastjson外部解决逻辑,jackson不反对该个性,不影响性能 |
禁用循环援用检测 | Feature.DisableCircularReferenceDetect | 敞开 | – | – | fastjson外部解决逻辑,jackson不反对该个性,不影响性能 |
对于没有值的字符串属性设置为空串 | Feature.InitStringFieldAsEmpty | 敞开 | – | – | jackson不反对该个性,然而能够通过@JsonSetter 的nulls() 和contentNulls() 别离设置Bean以及Array/Collection的元素对null 的解决形式。例如Nulls.AS_EMPTY 就会将null 设置为JsonDeserializer.getEmptyValue |
非标准个性,容许将数组依照字段程序解析成Java Bean,例如"[1001,\"xx\",33]" 能够等价为"{\"id\": 10001, \"name\": \"xx\", \"age\": 33}" |
Feature.SupportArrayToBean | 敞开 | – | – | 非标准个性,且应用场景较少,jackson不反对该个性 |
解析后属性放弃原来的程序 | Feature.OrderedField | 敞开 | – | – | – |
禁用特殊字符查看 | Feature.DisableSpecialKeyDetect | 敞开 | – | – | – |
应用对象数组而不是汇合 | Feature.UseObjectArray | 敞开 | DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY | 敞开 | 放弃敞开 |
反对解析没有setter办法的非public属性 | Feature.SupportNonPublicField | 敞开 | – | – | jaskson能够通过ObjectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) 来达到雷同的目标 |
禁用fastjson的AUTOTYPE个性,即不依照json字符串中的@type 主动抉择反序列化类 |
Feature.IgnoreAutoType | 敞开 | – | – | jackson的PolymorphicDeserialization默认是反对Object.class 、abstract classes 、interfaces 属性的AUTO Type,然而该个性容易导致安全漏洞,强烈建议应用ObjectMapper.disableDefaultTyping() 设置为只容许@JsonTypeInfo 失效 |
禁用属性智能匹配,例如下划线主动匹配驼峰等 | Feature.DisableFieldSmartMatch | 敞开 | – | – | jackson能够通过ObjectMapper.setPropertyNamingStrategy() 达到雷同的目标,但这种是针对一个json串的对立策略,如果要在一个json串中应用不同的策略则能够应用@JsonProperty.value() 指定字段名 |
启用fastjson的autotype性能,即依据json字符串中的@type 主动抉择反序列化的类 |
Feature.SupportAutoType | 敞开 | ObjectMapper.DefaultTyping.* | 开启 | jackson的PolymorphicDeserialization反对不同级别的AUTO TYPE,然而这个性能容易导致安全漏洞,强烈建议应用ObjectMapper.disableDefaultTyping() 设置为只容许@JsonTypeInfo 失效 |
解析时将未用引号蕴含的json字段名作为String类型存储,否则只能用原始类型获取key的值。例如String text="{123:\"abc\"}" 在启用了NonStringKeyAsString 后能够通过JSON.parseObject(text).getString("123") 的形式获取到"abc" ,而在不启用NonStringKeyAsString 时,JSON.parseObject(text).getString("123") 只能失去null ,必须通过JSON.parseObject(text).get(123) 的形式能力获取到"abc" 。 |
Feature.NonStringKeyAsString | 敞开 | – | – | 非标准个性,jackson并不反对 |
自定义"{\"key\":value}" 解析成Map 实例,否则解析为JSONObject |
Feature.CustomMapDeserializer | 敞开 | – | – | jackson没有相应的全局个性,然而能够通过TypeReference 达到雷同的成果 |
枚举未匹配到时抛出异样,否则解析为null |
Feature.ErrorOnEnumNotMatch | 敞开 | DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL | 敞开 | fastjson默认解析为null ,jackson则相同,默认会抛异样,倡议采纳jackson默认行为 |
反序列化fastjson和jackson的个性TestCase见DeserializationUseJacksonReplaceFastJsonTest.java
Serialization
fastjson将Java Bean序列化成json字符串通常也是应用com.alibaba.fastjson.JSON
的静态方法(JSONObject
和JSONArray
的静态方法也是来自于JSON
),罕用的有以下几个API:
public static String toJSONString(Object object); public static String toJSONString(Object object, SerializerFeature... features); public static String toJSONStringWithDateFormat(Object object, String dateFormat, SerializerFeature... features); public static String toJSONString(Object object, boolean prettyFormat); public static void writeJSONString(Writer writer, Object object, SerializerFeature... features);
从办法入参也能看出,在序列化时,fastjson的个性由SerializerFeature
管制,钻研toJSONString
的源码后,发现最终都会调用以下办法:
public static String toJSONString(Object object, SerializeConfig config, SerializeFilter[] filters, String dateFormat, int defaultFeatures, SerializerFeature... features) { SerializeWriter out = new SerializeWriter(null, defaultFeatures, features); try { JSONSerializer serializer = new JSONSerializer(out, config); if (dateFormat != null && dateFormat.length() != 0) { serializer.setDateFormat(dateFormat); serializer.config(SerializerFeature.WriteDateUseDateFormat, true); } if (filters != null) { for (SerializeFilter filter : filters) { serializer.addFilter(filter); } } serializer.write(object); return out.toString(); } finally { out.close(); } }
通过IDE搜寻usage后,发现当没有作为基准解析个性开关的defaultFeatures
入参时,都是应用的DEFAULT_GENERATE_FEATURE
作为基准解析个性开关,以下是JSON.DEFAULT_GENERATE_FEATURE
的实例化代码:
static { int features = 0; features |= SerializerFeature.QuoteFieldNames.getMask(); features |= SerializerFeature.SkipTransientField.getMask(); features |= SerializerFeature.WriteEnumUsingName.getMask(); features |= SerializerFeature.SortField.getMask(); DEFAULT_GENERATE_FEATURE = features; config(IOUtils.DEFAULT_PROPERTIES); }
fastjson还会从环境变量中读取配置来批改DEFAULT_GENERATE_FEATURE
(尽管很少会有人这么做),但最好还是通过理论运行一下程序来确认你的环境中的理论解析个性开关。
@Test public void printFastJsonDefaultGenerateFeature() { for (SerializerFeature feature : SerializerFeature.values()) { if (SerializerFeature.isEnabled(JSON.DEFAULT_GENERATE_FEATURE, feature)) { System.out.println(feature); } } }
fastjson 和 jackson的序列化个性对照表
fastjson个性阐明 | fastjson枚举 | fastjson默认状态 | jackson枚举 | jackson默认状态 | jackson个性阐明 |
---|---|---|---|---|---|
输入的json字段名被引号蕴含 | SerializerFeature.QuoteFieldNames | 开启 | JsonGenerator.Feature.QUOTE_FIELD_NAMES | 开启 | 放弃开启 |
序列化时应用单引号,而不是应用双引号 | SerializerFeature.UseSingleQuotes | 敞开 | – | – | jackson不反对该个性 |
序列化时,value为null 的key或field也输入 |
SerializerFeature.WriteMapNullValue | 敞开 | JsonInclude.Include.ALWAYS | 开启 | 倡议按需抉择。留神SerializationFeature.WRITE_NULL_MAP_VALUES 从2.9已废除,且会被JsonInclude.Include 给笼罩 |
序列化枚举时应用枚举类型的toString() 办法,和SerializerFeature.WriteEnumUsingName 互斥 |
SerializerFeature.WriteEnumUsingToString | 敞开 | SerializationFeature.WRITE_ENUMS_USING_TO_STRING | 敞开 | 倡议敞开,或者和反序列化的DeserializationFeature.READ_ENUMS_USING_TO_STRING 保持一致 |
序列化枚举时应用枚举类型的name() 办法,和SerializerFeature.WriteEnumUsingToString 互斥 |
SerializerFeature.WriteEnumUsingName | 开启 | – | – | jackson的默认行为,无需配置 |
序列化时对Date、Calendar等类型应用ISO8601格局进行格式化,否则以timestamp模式输入Long数字 | SerializerFeature.UseISO8601DateFormat | 敞开 | SerializationFeature.WRITE_DATES_AS_TIMESTAMPS | 开启 | jackson和fastjson的默认行为都是将Date数据输入为Long,倡议依据不同的场景抉择是否须要格式化日期 |
序列化List类型数据时将null 输入为"[]" |
SerializerFeature.WriteNullListAsEmpty | 敞开 | – | – | 能够通过PropertyFilter /SerializerFactory.withSerializerModifier(BeanSerializerModifier) 任一一种形式达到雷同成果,举荐应用PropertyFilter |
序列化String类型的field时将null 输入为"" |
SerializerFeature.WriteNullStringAsEmpty | 敞开 | – | – | 能够通过PropertyFilter /SerializerFactory.withSerializerModifier(BeanSerializerModifier) 任一一种形式达到雷同成果,举荐应用PropertyFilter |
序列化Number类型的field时将null 输入为0 |
SerializerFeature.WriteNullNumberAsZero | 敞开 | – | – | 能够通过PropertyFilter /SerializerFactory.withSerializerModifier(BeanSerializerModifier) 任一一种形式达到雷同成果,举荐应用PropertyFilter |
序列化Boolean类型的field时将null 输入为false |
SerializerFeature.WriteNullBooleanAsFalse | 敞开 | – | – | 能够通过PropertyFilter /SerializerFactory.withSerializerModifier(BeanSerializerModifier) 任一一种形式达到雷同成果,举荐应用PropertyFilter |
序列化时疏忽transient 润饰的field |
SerializerFeature.SkipTransientField | 开启 | MapperFeature.PROPAGATE_TRANSIENT_MARKER | 敞开 | 倡议放弃敞开,通过@JsonIgnore 或者FilterProvider 来指定疏忽的属性 |
序列化时,如果未指定order ,则将field依照getter 办法的字典程序排序 |
SerializerFeature.SortField | 开启 | MapperFeature.SORT_PROPERTIES_ALPHABETICALLY | 敞开 | 倡议敞开,排序会影响序列化性能(fastjson在反序列化时反对依照field程序读取解析,因而排序后的json串有利于进步fastjson的解析性能,但jackson并没有该个性) |
把\t 做本义输入,已废除,即便开启也有效 |
SerializerFeature.WriteTabAsSpecial | 敞开 | – | – | – |
格式化json输入 | SerializerFeature.PrettyFormat | 敞开 | SerializationFeature.INDENT_OUTPUT | 敞开 | 倡议放弃敞开,格式化能够交给前端实现 |
序列化时把类型名称写入json | SerializerFeature.WriteClassName | 敞开 | – | – | jackson能够通过@JsonTypeInfo 达到相似的成果,参见Jackson Annotation Examples |
序列化时打消对同一对象循环援用的问题 | SerializerFeature.DisableCircularReferenceDetect | 敞开 | SerializationFeature.FAIL_ON_SELF_REFERENCES | 开启 | 放弃开启,防止循环援用 |
对斜杠’/’进行本义 | SerializerFeature.WriteSlashAsSpecial | 敞开 | – | – | jackson能够通过自定义Serializer 实现雷同成果,按需设置 |
将中文都会序列化为\uXXXX 格局,字节数会多一些,然而能兼容IE 6 |
SerializerFeature.BrowserCompatible | 敞开 | – | – | jackson能够通过自定义Serializer 实现雷同成果,按需设置 |
全局批改日期格局,默认应用JSON.DEFFAULT_DATE_FORMAT |
SerializerFeature.WriteDateUseDateFormat | 敞开 | – | – | jackson能够通过@JsonFormat.pattern() 、ObjectMapper.setDateFormat() 等形式实现雷同成果 |
序列化时不把最外层的类型名称写入json | SerializerFeature.NotWriteRootClassName | 敞开 | – | – | jackson能够通过@JsonRootName 达到相似的成果,参见Jackson Annotation Examples |
不本义特殊字符,已废除,即便开启也有效 | SerializerFeature.DisableCheckSpecialChar | 敞开 | – | – | – |
将Bean序列化时将field值按程序当成json数组输入,而不是json object,同时不会输入fieldName,例如:{"id":123,"name":"xxx"} 会输入成[123,"xxx"] |
SerializerFeature.BeanToArray | 敞开 | – | – | 非标准个性,jackson并不反对 |
序列化Map时将非String类型的key作为String类型输入,例如:{123:231} 会输入成{"123":231} |
SerializerFeature.WriteNonStringKeyAsString | 敞开 | – | – | 非标准个性,jackson并不反对 |
序列化Byte、Short、Integer、Long、Float、Double、Boolean 及其对应原始类型field时,如果属性值为各自类型的默认值(如0、0F、0L ),则不会输入该属性 |
SerializerFeature.NotWriteDefaultValue | 敞开 | – | – | 非标准个性,jackson并不反对 |
序列化时将( 、) 、> 、< 以unicode编码输入 |
SerializerFeature.BrowserSecure | 敞开 | – | – | jackson能够通过自定义Serializer 实现雷同成果,按需设置,通常能够交给前端解决 |
序列化时疏忽没有理论属性对应的getter办法 | SerializerFeature.IgnoreNonFieldGetter | 敞开 | – | – | – |
序列化时把非String类型数据当作String类型输入 | SerializerFeature.WriteNonStringValueAsString | 敞开 | – | – | jackson有一个相似的个性JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS 能够将数字作为字符串输入,但没有笼罩所有非String类型 |
序列化时疏忽会抛异样的getter办法 | SerializerFeature.IgnoreErrorGetter | 敞开 | – | – | – |
序列化时将BigDecimal应用toPlainString()输入 | SerializerFeature.WriteBigDecimalAsPlain | 敞开 | JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN | 敞开 | 按需开启 |
序列化时对Map依照Key进行排序 | SerializerFeature.MapSortField | 敞开 | SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS | 敞开 | 倡议敞开,开启会影响性能 |
序列化fastjson和jackson的个性TestCase见SerializationUseJacksonReplaceFastJsonTest.java
Annotation
fastjsonzhu绝对于jackson来说注解的性能划分的并没有那么细,因而fastjson的一个注解可能等价于jackson多个注解的组合。
@JSONPOJOBuilder
指定反序列化时创立java对象应用的build办法,对应jackson的@JsonPOJOBuilder
。
@JSONCreator
指定反序列化时创立java对象应用的构造方法,对应jackson的@JsonCreator
。
@JSONField
指定序列化和反序列化field时的行为。反序列化时,等价于@JsonProperty
+ @JsonDeserialize
+ @JsonUnwrapped
+ @JsonFormat
+ @JsonAlias
;序列化时,等价于@JsonProperty
+ @JsonSerialize
+ @JsonUnwrapped
+ @JsonFormat
+ @JsonRawValue
+ @JsonView
。
@Retention(RetentionPolic<i style="color:transparent">来源gaodai$ma#com搞$代*码网</i>y.RUNTIME) @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER }) public @interface JSONField { // 序列化和反序列化时的字段程序,等价于jackson的@JsonProperty.index() int ordinal() default 0; // 序列化和反序列化时的字段名称映射,等价于jackson的@JsonProperty.value() String name() default ""; // 序列化和反序列化时的数据格式(日期格局、16进制等等),等价于jackson的@JsonFormat.shape() + @JsonFormat.pattern() String format() default ""; // 字段是否序列化,等价于jackson的@JsonProperty.access() boolean serialize() default true; // 字段是否反序列化,等价于jackson的@JsonProperty.access() boolean deserialize() default true; // 序列化个性,等价于jackson的@JsonProperty.with() SerializerFeature[] serialzeFeatures() default {}; // 反序列化个性,等价于jackson的@JsonFormat.with() Feature[] parseFeatures() default {}; // 对属性进行打标,便于在序列化时进行exclude或include,等价于jackson的@JsonView String label() default ""; // 序列化时将字段内容间接输入,不通过本义,等价于jackson的@JsonRawValue boolean jsonDirect() default false; // 指定序列化时应用的Serializer Class,等价于jackson的@JsonSerialize Class<?> serializeUsing() default Void.class; // 指定反序列化时应用的Deserializer Class,等价于jackson的@JsonDeserialize Class<?> deserializeUsing() default Void.class; // 指定反序列化时应用的字段别名,等价于jackson的@JsonAlias String[] alternateNames() default {}; // 将字段的子属性映射到父节点上,等价于jackson的@JsonUnwrapped boolean unwrapped() default false; // 指定序列化时字段为null时应用的默认值,等价于jackson的@JsonProperty.defaultValue() String defaultValue() default ""; }
unwrapped
的用法能够参考AnnotationUseJacksonReplaceFastJsonTest.java中的testJSONFieldUnwrapped
。
@JSONType
指定序列化和反序列化一个Java Bean时的行为。
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE }) public @interface JSONType { // 是否应用asm优化,jackson无对应个性 boolean asm() default true; // 序列化和反序列化时的field排序,等价于jackson的@JsonPropertyOrder.value() String[] orders() default {}; // 序列化和反序列化时蕴含的field,等价于jackson的 String[] includes() default {}; // 序列化和反序列化时疏忽的field,等价于jackson的@JsonIgnoreProperties String[] ignores() default {}; // 序列化个性,等价于jackson的@JsonProperty.with() SerializerFeature[] serialzeFeatures() default {}; // 反序列化个性,等价于jackson的@JsonFormat.with() Feature[] parseFeatures() default {}; // 序列化时是否根据field字母程序排序,等价于jackson的@JsonPropertyOrder.alphabetic() boolean alphabetic() default true; // 反序列化多态类型时,如果依据其余typeName等形式无奈找到正确的子类时,默认应用的子类,等价于jackson的@JsonTypeInfo.defaultImpl() Class<?> mappingTo() default Void.class; // 反序列化时指定java bean builder类(必须是@JSONPOJOBuilder注解的类),等价于jackson的@JsonDeserialize.builder() Class<?> builder() default Void.class; // 申明这个类型的别名,反序列化多态类型时应用,等价于jackson的@JsonTypeName String typeName() default ""; // 反序列化某个接口或抽象类或父类的子类时指定依据哪个字段的值和子类的typeName相等来决定具体实现类,等价于jackson的@JsonTypeInfo.use() = Id.CUSTOM + @JsonTypeInfo.property() String typeKey() default ""; // 反序列化某个接口或抽象类或父类的子类时指定能够反序列化的子类类型,等价于jackson的@JsonSubTypes Class<?>[] seeAlso() default{}; // 指定序列化时应用的Serializer Class,等价于jackson的@JsonSerialize Class<?> serializer() default Void.class; // 指定反序列化时应用的Deserializer Class,等价于jackson的@JsonDeserialize Class<?> deserializer() default Void.class; // 序列化时,如果filed是枚举类型,则和一般的java bean一样输入枚举的filed,而不是通常应用的Enum.name()值,jackson没有对应个性 boolean serializeEnumAsJavaBean() default false; // 指定json和Java bean之间的字段名称映射策略,等价于jackson的@JsonNaming PropertyNamingStrategy naming() default PropertyNamingStrategy.CamelCase; // 指定序列化时应用的Serialize filter,等价于jackson的@JsonFilter Class<? extends SerializeFilter>[] serialzeFilters() default {}; }
JSONObject
& JSONArray
首先来看看fastjon中JSONObject
和JSONArray
的源码:
public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler { private final Map<String, Object> map; ... } public class JSONArray extends JSON implements List<Object>, Cloneable, RandomAccess, Serializable { private static final long serialVersionUID = 1L; private final List<Object> list; protected transient Object relatedArray; protected transient Type componentType; ... }
从源码就能够发现,JSONObject
理论是一个Map<String, Object>
,而JSONArray
理论是一个List<JSONObject>
。因而能够将JSONObject
类型改为Map<String, Object>
,而JSONArray
类型改为List<Object>
。然而这种形式就会导致下层API呈现大量批改,因为短少了JSONObject
和JSONArray
提供的多种便当的类型转换办法。如果想要临时保留JSONObject
和JSONArray
,此时能够采取一种取巧的办法。
临时保留JSONObject
& JSONArray
的过渡办法
jackson官网提供了对org.json
库的数据类型反对jackson-datatype-json-org
,因而能够将com.alibaba.fastjson.JSONObject
替换为org.json.JSONObject
,com.alibaba.fastjson.JSONArray
替换为org.json.JSONArray
,这两个类库的对象API大致相同,当然一些细小的改变还是防止不了的。如果想齐全不改下层代码,那也能够参考jackson-datatype-json-org和jackson-datatype-json-lib本人实现jackson对fastjson的数据类型的binder。
larva-zhang/jackson-datatype-fastjson欢送大家应用或提issues。
JSONPath
应用json-path/JsonPath就能轻松替换fastjson的JSONPath,而且性能比fastjson更弱小。只需参考JsonProvider SPI应用JacksonJsonProvider
代替json-path/JsonPath默认的JsonSmartJsonProvider
即可。
自定义扩大
自定义Deserializer
fastjson中实现自定义Deserializer的办法通常是实现ObjectDeserializer
接口的deserialze
办法
<T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName);
在jackson中实现自定义Serializer的办法则通常是继承StdDeserializer
抽象类,重写deserialize
办法
public abstract T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException;
自定义Serializer
fastjson中实现自定义Serializer的办法通常是实现ObjectSerializer
接口的write
办法
void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException;
在jackson中实现自定义Serializer的办法则通常是继承StdSerializer
抽象类,重写serialize
办法
public abstract void serialize(T value, JsonGenerator gen, SerializerProvider serializers) throws IOException;
自定义Serialize Filter
fastjson中提供了6种SerializeFilter
,详见fastjson/wiki/SerializeFilter。而在jackson中则是倡议继承SimpleBeanPropertyFilter
。
近期热文举荐:
1.1,000+ 道 Java面试题及答案整顿(2021最新版)
2.终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!
5.《Java开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞+转发哦!