作者:larva-zhh\
起源:www.cnblogs.com/larva-zhh/p/11544317.html

为什么要替换fastjson

工程里大量应用了fastjson作为序列化和反序列化框架,甚至ORM在解决局部字段也依赖fastjson进行序列化和反序列化。那么作为大量应用的根底框架,为什么还要进行替换呢?

起因有以下几点:

  1. fastjson太过于偏重性能,对于局部高级个性反对不够,而且局部自定义个性齐全偏离了json和js标准导致和其余框架不兼容;
  2. fastjson文档缺失较多,局部Feature甚至没有文档,而且代码短少正文较为艰涩;
  3. 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常见的应用场景就是序列化和反序列化,偶然会有JSONObjectJSONArray实例的相干操作。

以下步骤的源码剖析基于以下版本:

  • 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的静态方法(JSONObjectJSONArray的静态方法也是来自于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(尽管很少会有人这么做),但最好还是通过理论运行一下程序来确认你的环境中的理论解析个性开关。

@Testpublic 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.000Z2018-05-31T19:13:42.000+07:00Feature.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不反对该个性,不影响性能
禁用ASMFeature.DisableASM敞开--fastjson外部解决逻辑,jackson不反对该个性,不影响性能
禁用循环援用检测Feature.DisableCircularReferenceDetect敞开--fastjson外部解决逻辑,jackson不反对该个性,不影响性能
对于没有值的字符串属性设置为空串Feature.InitStringFieldAsEmpty敞开--jackson不反对该个性,然而能够通过@JsonSetternulls()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.classabstract classesinterfaces属性的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实例,否则解析为JSONObjectFeature.CustomMapDeserializer敞开--jackson没有相应的全局个性,然而能够通过TypeReference达到雷同的成果
枚举未匹配到时抛出异样,否则解析为nullFeature.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的静态方法(JSONObjectJSONArray的静态方法也是来自于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(尽管很少会有人这么做),但最好还是通过理论运行一下程序来确认你的环境中的理论解析个性开关。

@Testpublic 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输入为0SerializerFeature.WriteNullNumberAsZero敞开--能够通过PropertyFilter/SerializerFactory.withSerializerModifier(BeanSerializerModifier)任一一种形式达到雷同成果,举荐应用PropertyFilter
序列化Boolean类型的field时将null输入为falseSerializerFeature.WriteNullBooleanAsFalse敞开--能够通过PropertyFilter/SerializerFactory.withSerializerModifier(BeanSerializerModifier)任一一种形式达到雷同成果,举荐应用PropertyFilter
序列化时疏忽transient润饰的fieldSerializerFeature.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敞开倡议放弃敞开,格式化能够交给前端实现
序列化时把类型名称写入jsonSerializerFeature.WriteClassName敞开--jackson能够通过@JsonTypeInfo达到相似的成果,参见Jackson Annotation Examples
序列化时打消对同一对象循环援用的问题SerializerFeature.DisableCircularReferenceDetect敞开SerializationFeature.FAIL_ON_SELF_REFERENCES开启放弃开启,防止循环援用
对斜杠'/'进行本义SerializerFeature.WriteSlashAsSpecial敞开--jackson能够通过自定义Serializer实现雷同成果,按需设置
将中文都会序列化为\uXXXX格局,字节数会多一些,然而能兼容IE 6SerializerFeature.BrowserCompatible敞开--jackson能够通过自定义Serializer实现雷同成果,按需设置
全局批改日期格局,默认应用JSON.DEFFAULT_DATE_FORMATSerializerFeature.WriteDateUseDateFormat敞开--jackson能够通过@JsonFormat.pattern()ObjectMapper.setDateFormat()等形式实现雷同成果
序列化时不把最外层的类型名称写入jsonSerializerFeature.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(RetentionPolicy.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中JSONObjectJSONArray的源码:

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呈现大量批改,因为短少了JSONObjectJSONArray提供的多种便当的类型转换办法。如果想要临时保留JSONObjectJSONArray,此时能够采取一种取巧的办法。

临时保留JSONObject & JSONArray的过渡办法

jackson官网提供了对org.json库的数据类型反对jackson-datatype-json-org,因而能够将com.alibaba.fastjson.JSONObject替换为org.json.JSONObjectcom.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开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!