用了幾年的 Fastjson,我最終替換成了Jackson!

做者:larva-zhh\
來源:www.cnblogs.com/larva-zhh/p/11544317.htmlhtml

爲何要替換fastjson

工程裏大量使用了fastjson做爲序列化和反序列化框架,甚至ORM在處理部分字段也依賴fastjson進行序列化和反序列化。那麼做爲大量使用的基礎框架,爲何還要進行替換呢?前端

緣由有如下幾點:java

  1. fastjson太過於側重性能,對於部分高級特性支持不夠,並且部分自定義特性徹底偏離了json和js規範致使和其餘框架不兼容;
  2. fastjson文檔缺失較多,部分Feature甚至沒有文檔,並且代碼缺乏註釋較爲晦澀;
  3. fastjson的CVE bug監測較弱,不少CVE數據庫網站上有關fastjson的CVE寥寥無幾,例如近期的AutoType致使的高危漏洞,雖然和Jackson的PolymorphicDeserialization是一樣的bug,可是CVE網站上幾乎沒有fastjson的bug報告。

框架選型

參考mvnrepository json libraries,根據流行度排序後前十名框架:git

  • jackson2(com.fasterxml.jackson)
  • gson
  • org.json
  • jackson1(com.codehuas.jackson)
  • fastjson
  • cheshire
  • json-simple

jackson1是已通過時的框架,所以能夠忽略,cheshire和json-simple排名尚且不如fastjson,也忽略,剩餘jackson二、gson以及org.json,其中org.json的使用量(usage)遠小於jackson2(方便起見,下文均以jackson均指代jackson2)和gson,所以org.json也能夠排除了。github

關於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。spring

PS: Jackson 2.10.0開始嘗試基於新的API使用白名單機制來避免RCE漏洞,詳見https://github.com/FasterXML/...,效果尚待觀察。數據庫

替換fastjson

fastjson常見的使用場景就是序列化和反序列化,偶爾會有JSONObjectJSONArray實例的相關操做。json

如下步驟的源碼分析基於如下版本:數組

  • 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(雖然不多會有人這麼作),但最好仍是經過實際運行一下程序來確認你的環境中的實際解析特性開關。

@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.000Z2018-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不支持該特性,可是能夠經過@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實例,不然解析爲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的靜態方法(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(雖然不多會有人這麼作),但最好仍是經過實際運行一下程序來確認你的環境中的實際解析特性開關。

@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(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開發手冊(嵩山版)》最新發布,速速下載!

以爲不錯,別忘了隨手點贊+轉發哦!

相關文章
相關標籤/搜索