<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Jackson!超好用~

          共 28780字,需瀏覽 58分鐘

           ·

          2021-03-31 11:16

          不點藍字,我們哪來故事?

          每天 11 點更新文章,餓了點外賣,點擊 ??《無門檻外賣優(yōu)惠券,每天免費領(lǐng)!》

          來源:cnblogs.com/larva-zhh/p/11544317.html

          • 為什么要替換fastjson
          • 框架選型
          • 替換fastjson
            • Deserialization
            • Serialization
            • Annotation
            • JSONObject & JSONArray
            • JSONPath
            • 自定義擴展

          為什么要替換fastjson

          工程里大量使用了fastjson作為序列化和反序列化框架,甚至ORM在處理部分字段也依賴fastjson進行序列化和反序列化。那么作為大量使用的基礎(chǔ)框架,為什么還要進行替換呢?

          原因有以下幾點:

          1. fastjson太過于側(cè)重性能,對于部分高級特性支持不夠,而且部分自定義特性完全偏離了json和js規(guī)范導(dǎo)致和其他框架不兼容;
          2. fastjson文檔缺失較多,部分Feature甚至沒有文檔,而且代碼缺少注釋較為晦澀;
          3. fastjson的CVE bug監(jiān)測較弱,很多CVE數(shù)據(jù)庫網(wǎng)站上有關(guān)fastjson的CVE寥寥無幾,例如近期的AutoType導(dǎo)致的高危漏洞,雖然和Jackson的PolymorphicDeserialization是同樣的bug,但是CVE網(wǎng)站上幾乎沒有fastjson的bug報告。

          框架選型

          參考mvnrepository json libraries,根據(jù)流行度排序后前十名框架:

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

          jackson1是已經(jīng)過時的框架,因此可以忽略,cheshire和json-simple排名尚且不如fastjson,也忽略,剩余jackson2、gson以及org.json,其中org.json的使用量(usage)遠小于jackson2(方便起見,下文均以jackson均指代jackson2)和gson,因此org.json也可以排除了。

          關(guān)于jackson和gson的比較文章有很多,stackoverflow上自行搜索,下面僅推薦幾篇blog:

          • jackson vs gson
          • JSON in Java
          • the ultimate json library json-simple vs gson vs jackson vs json

          在功能特性支持、穩(wěn)定性、可擴展性、易用性以及社區(qū)活躍度上 jackson 和 gson 差不多,入門教程可以分別參考baeldung jackson系列 以及 baeldung gson系列。但是jackson有更多現(xiàn)成的類庫兼容支持例如jackson-datatype-commons-lang3,以及更豐富的輸出數(shù)據(jù)格式支持例如jackson-dataformat-yaml,而且spring框架默認使用jackson,因此最終我選擇使用jackson。

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

          替換fastjson

          fastjson常見的使用場景就是序列化和反序列化,偶爾會有JSONObjectJSONArray實例的相關(guān)操作。

          以下步驟的源碼分析基于以下版本:

          • 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的靜態(tài)方法(JSONObjectJSONArray的靜態(tài)方法也是來自于JSON),常用的有以下幾個API:

          public static JSONObject parseObject(String text);

          public static JSONObject parseObject(String text, Feature... features);

          public static <T> parseObject(String text, Class<T> clazz);

          public static <T> parseObject(String text, Class<T> clazz, Feature... features);

          public static <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);

          從方法入?yún)⒕湍懿碌?,fastjson在執(zhí)行反序列化時的Parse行為由com.alibaba.fastjson.parser.Feature指定。研究parseObject的源碼后,發(fā)現(xiàn)底層最終都是使用的以下方法:

          public static <T> parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor, int featureValues, Feature... features) {
                  if (input == null) {
                      return null;
                  }

                  // featureValues作為基準解析特性開關(guān)值
                  // 入?yún)eatures和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后,發(fā)現(xiàn)當沒有作為基準解析特性開關(guān)的featureValues入?yún)r,都是使用的DEFAULT_PARSE_FEATURE作為基準解析特性開關(guān),以下是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還會從環(huán)境變量中讀取配置來修改DEFAULT_PARSER_FEATURE(雖然很少會有人這么做),但最好還是通過實際運行一下程序來確認你的環(huán)境中的實際解析特性開關(guān)。

              @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默認狀態(tài)jackson枚舉jackson默認狀態(tài)jackson特性說明
          Parser close時自動關(guān)閉為創(chuàng)建Parser實例而創(chuàng)建的底層InputStream以及Reader等輸入流Feature.AutoCloseSource開啟JsonParser.Feature.AUTO_CLOSE_SOURCE開啟保持開啟
          允許json字符串中帶注釋Feature.AllowComment關(guān)閉JsonParser.Feature.ALLOW_COMMENTS關(guān)閉根據(jù)系統(tǒng)的json數(shù)據(jù)情況開啟
          允許json字段名不被引號包括起來Feature.AllowUnQuotedFieldNames開啟JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES關(guān)閉根據(jù)系統(tǒng)的json數(shù)據(jù)情況開啟
          允許json字段名使用單引號包括起來Feature.AllowSingleQuotes開啟JsonParser.Feature.ALLOW_SINGLE_QUOTES關(guān)閉根據(jù)系統(tǒng)的json數(shù)據(jù)情況開啟
          將json字段名作為字面量緩存起來,即fieldName.intern()Feature.InternFieldNames開啟--jackson默認使用InternCache緩存了PropertyName
          識別ISO8601格式的日期字符串,例如:2018-05-31T19:13:42.000Z2018-05-31T19:13:42.000+07:00Feature.AllowISO8601DateFormat關(guān)閉--jackson默認支持ISO8601格式日期字符串的解析,并且也可以通過ObjectMapper.setDateFormat指定解析格式
          忽略json中包含的連續(xù)的多個逗號,非標準特性Feature.AllowArbitraryCommas關(guān)閉--jackson不支持該特性,且該特性是非標準特性,因此可以忽略
          將json中的浮點數(shù)解析成BigDecimal對象,禁用后會解析成Double對象Feature.UseBigDecimal開啟DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS關(guān)閉建議開啟
          解析時忽略未知的字段繼續(xù)完成解析Feature.IgnoreNotMatch開啟DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES開啟jackson默認開啟遇到未知屬性需要拋異常,因此如要和fastjson保持一致則需要關(guān)閉該特性
          如果你用fastjson序列化的文本,輸出的結(jié)果是按照fieldName排序輸出的,parser時也能利用這個順序進行優(yōu)化讀取。這種情況下,parser能夠獲得非常好的性能Feature.SortFeidFastMatch關(guān)閉--fastjson內(nèi)部處理邏輯,jackson不支持該特性,不影響功能
          禁用ASMFeature.DisableASM關(guān)閉--fastjson內(nèi)部處理邏輯,jackson不支持該特性,不影響功能
          禁用循環(huán)引用檢測Feature.DisableCircularReferenceDetect關(guān)閉--fastjson內(nèi)部處理邏輯,jackson不支持該特性,不影響功能
          對于沒有值的字符串屬性設(shè)置為空串Feature.InitStringFieldAsEmpty關(guān)閉--jackson不支持該特性,但是可以通過@JsonSetternulls()contentNulls()分別設(shè)置Bean以及Array/Collection的元素對null的處理方式。例如Nulls.AS_EMPTY就會將null設(shè)置為JsonDeserializer.getEmptyValue
          非標準特性,允許將數(shù)組按照字段順序解析成Java Bean,例如"[1001,\"xx\",33]"可以等價為"{\"id\": 10001, \"name\": \"xx\", \"age\": 33}"Feature.SupportArrayToBean關(guān)閉--非標準特性,且使用場景較少,jackson不支持該特性
          解析后屬性保持原來的順序Feature.OrderedField關(guān)閉---
          禁用特殊字符檢查Feature.DisableSpecialKeyDetect關(guān)閉---
          使用對象數(shù)組而不是集合Feature.UseObjectArray關(guān)閉DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY關(guān)閉保持關(guān)閉
          支持解析沒有setter方法的非public屬性Feature.SupportNonPublicField關(guān)閉--jaskson可以通過ObjectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)來達到相同的目的
          禁用fastjson的AUTOTYPE特性,即不按照json字符串中的@type自動選擇反序列化類Feature.IgnoreAutoType關(guān)閉--jackson的PolymorphicDeserialization默認是支持Object.class、abstract classes、interfaces屬性的AUTO Type,但是該特性容易導(dǎo)致安全漏洞,強烈建議使用ObjectMapper.disableDefaultTyping()設(shè)置為只允許@JsonTypeInfo生效
          禁用屬性智能匹配,例如下劃線自動匹配駝峰等Feature.DisableFieldSmartMatch關(guān)閉--jackson可以通過ObjectMapper.setPropertyNamingStrategy()達到相同的目的,但這種是針對一個json串的統(tǒng)一策略,如果要在一個json串中使用不同的策略則可以使用@JsonProperty.value()指定字段名
          啟用fastjson的autotype功能,即根據(jù)json字符串中的@type自動選擇反序列化的類Feature.SupportAutoType關(guān)閉ObjectMapper.DefaultTyping.*開啟jackson的PolymorphicDeserialization支持不同級別的AUTO TYPE,但是這個功能容易導(dǎo)致安全漏洞,強烈建議使用ObjectMapper.disableDefaultTyping()設(shè)置為只允許@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關(guān)閉--非標準特性,jackson并不支持
          自定義"{\"key\":value}"解析成Map實例,否則解析為JSONObjectFeature.CustomMapDeserializer關(guān)閉--jackson沒有相應(yīng)的全局特性,但是可以通過TypeReference達到相同的效果
          枚舉未匹配到時拋出異常,否則解析為nullFeature.ErrorOnEnumNotMatch關(guān)閉DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL關(guān)閉fastjson默認解析為null,jackson則相反,默認會拋異常,建議采用jackson默認行為

          反序列化fastjson和jackson的特性TestCase見DeserializationUseJacksonReplaceFastJsonTest.java

          Serialization

          fastjson將Java Bean序列化成json字符串通常也是使用com.alibaba.fastjson.JSON的靜態(tài)方法(JSONObjectJSONArray的靜態(tài)方法也是來自于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);

          從方法入?yún)⒁材芸闯觯谛蛄谢瘯r,fastjson的特性由SerializerFeature控制,研究toJSONString的源碼后,發(fā)現(xiàn)最終都會調(diào)用以下方法:

           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后,發(fā)現(xiàn)當沒有作為基準解析特性開關(guān)的defaultFeatures入?yún)r,都是使用的DEFAULT_GENERATE_FEATURE作為基準解析特性開關(guān),以下是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還會從環(huán)境變量中讀取配置來修改DEFAULT_GENERATE_FEATURE(雖然很少會有人這么做),但最好還是通過實際運行一下程序來確認你的環(huán)境中的實際解析特性開關(guān)。

              @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默認狀態(tài)jackson枚舉jackson默認狀態(tài)jackson特性說明
          輸出的json字段名被引號包含SerializerFeature.QuoteFieldNames開啟JsonGenerator.Feature.QUOTE_FIELD_NAMES開啟保持開啟
          序列化時使用單引號,而不是使用雙引號SerializerFeature.UseSingleQuotes關(guān)閉--jackson不支持該特性
          序列化時,value為null的key或field也輸出SerializerFeature.WriteMapNullValue關(guān)閉JsonInclude.Include.ALWAYS開啟建議按需選擇。注意SerializationFeature.WRITE_NULL_MAP_VALUES從2.9已廢棄,且會被JsonInclude.Include給覆蓋
          序列化枚舉時使用枚舉類型的toString()方法,和SerializerFeature.WriteEnumUsingName互斥SerializerFeature.WriteEnumUsingToString關(guān)閉SerializationFeature.WRITE_ENUMS_USING_TO_STRING關(guān)閉建議關(guān)閉,或者和反序列化的DeserializationFeature.READ_ENUMS_USING_TO_STRING保持一致
          序列化枚舉時使用枚舉類型的name()方法,和SerializerFeature.WriteEnumUsingToString互斥SerializerFeature.WriteEnumUsingName開啟--jackson的默認行為,無需配置
          序列化時對Date、Calendar等類型使用ISO8601格式進行格式化,否則以timestamp形式輸出Long數(shù)字SerializerFeature.UseISO8601DateFormat關(guān)閉SerializationFeature.WRITE_DATES_AS_TIMESTAMPS開啟jackson和fastjson的默認行為都是將Date數(shù)據(jù)輸出為Long,建議根據(jù)不同的場景選擇是否需要格式化日期
          序列化List類型數(shù)據(jù)時將null輸出為"[]"SerializerFeature.WriteNullListAsEmpty關(guān)閉--可以通過PropertyFilter/SerializerFactory.withSerializerModifier(BeanSerializerModifier)任一一種方式達到相同效果,推薦使用PropertyFilter
          序列化String類型的field時將null輸出為""SerializerFeature.WriteNullStringAsEmpty關(guān)閉--可以通過PropertyFilter/SerializerFactory.withSerializerModifier(BeanSerializerModifier)任一一種方式達到相同效果,推薦使用PropertyFilter
          序列化Number類型的field時將null輸出為0SerializerFeature.WriteNullNumberAsZero關(guān)閉--可以通過PropertyFilter/SerializerFactory.withSerializerModifier(BeanSerializerModifier)任一一種方式達到相同效果,推薦使用PropertyFilter
          序列化Boolean類型的field時將null輸出為falseSerializerFeature.WriteNullBooleanAsFalse關(guān)閉--可以通過PropertyFilter/SerializerFactory.withSerializerModifier(BeanSerializerModifier)任一一種方式達到相同效果,推薦使用PropertyFilter
          序列化時忽略transient修飾的fieldSerializerFeature.SkipTransientField開啟MapperFeature.PROPAGATE_TRANSIENT_MARKER關(guān)閉建議保持關(guān)閉,通過@JsonIgnore或者FilterProvider來指定忽略的屬性
          序列化時,如果未指定order,則將field按照getter方法的字典順序排序SerializerFeature.SortField開啟MapperFeature.SORT_PROPERTIES_ALPHABETICALLY關(guān)閉建議關(guān)閉,排序會影響序列化性能(fastjson在反序列化時支持按照field順序讀取解析,因此排序后的json串有利于提高fastjson的解析性能,但jackson并沒有該特性)
          \t做轉(zhuǎn)義輸出,已廢棄,即使開啟也無效SerializerFeature.WriteTabAsSpecial關(guān)閉---
          格式化json輸出SerializerFeature.PrettyFormat關(guān)閉SerializationFeature.INDENT_OUTPUT關(guān)閉建議保持關(guān)閉,格式化可以交給前端完成
          序列化時把類型名稱寫入jsonSerializerFeature.WriteClassName關(guān)閉--jackson可以通過@JsonTypeInfo達到類似的效果,參見Jackson Annotation Examples
          序列化時消除對同一對象循環(huán)引用的問題SerializerFeature.DisableCircularReferenceDetect關(guān)閉SerializationFeature.FAIL_ON_SELF_REFERENCES開啟保持開啟,避免循環(huán)引用
          對斜杠'/'進行轉(zhuǎn)義SerializerFeature.WriteSlashAsSpecial關(guān)閉--jackson可以通過自定義Serializer實現(xiàn)相同效果,按需設(shè)置
          將中文都會序列化為\uXXXX格式,字節(jié)數(shù)會多一些,但是能兼容IE 6SerializerFeature.BrowserCompatible關(guān)閉--jackson可以通過自定義Serializer實現(xiàn)相同效果,按需設(shè)置
          全局修改日期格式,默認使用JSON.DEFFAULT_DATE_FORMATSerializerFeature.WriteDateUseDateFormat關(guān)閉--jackson可以通過@JsonFormat.pattern()、ObjectMapper.setDateFormat()等方式實現(xiàn)相同效果
          序列化時不把最外層的類型名稱寫入jsonSerializerFeature.NotWriteRootClassName關(guān)閉--jackson可以通過@JsonRootName達到類似的效果,參見Jackson Annotation Examples
          不轉(zhuǎn)義特殊字符,已廢棄,即使開啟也無效SerializerFeature.DisableCheckSpecialChar關(guān)閉---
          將Bean序列化時將field值按順序當成json數(shù)組輸出,而不是json object,同時不會輸出fieldName,例如:{"id":123,"name":"xxx"}會輸出成[123,"xxx"]SerializerFeature.BeanToArray關(guān)閉--非標準特性,jackson并不支持
          序列化Map時將非String類型的key作為String類型輸出,例如:{123:231}會輸出成{"123":231}SerializerFeature.WriteNonStringKeyAsString關(guān)閉--非標準特性,jackson并不支持
          序列化Byte、Short、Integer、Long、Float、Double、Boolean及其對應(yīng)原始類型field時,如果屬性值為各自類型的默認值(如0、0F、0L),則不會輸出該屬性SerializerFeature.NotWriteDefaultValue關(guān)閉--非標準特性,jackson并不支持
          序列化時將()、>、<以unicode編碼輸出SerializerFeature.BrowserSecure關(guān)閉--jackson可以通過自定義Serializer實現(xiàn)相同效果,按需設(shè)置,通常可以交給前端處理
          序列化時忽略沒有實際屬性對應(yīng)的getter方法SerializerFeature.IgnoreNonFieldGetter關(guān)閉---
          序列化時把非String類型數(shù)據(jù)當作String類型輸出SerializerFeature.WriteNonStringValueAsString關(guān)閉--jackson有一個類似的特性JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS可以將數(shù)字作為字符串輸出,但沒有覆蓋所有非String類型
          序列化時忽略會拋異常的getter方法SerializerFeature.IgnoreErrorGetter關(guān)閉---
          序列化時將BigDecimal使用toPlainString()輸出SerializerFeature.WriteBigDecimalAsPlain關(guān)閉JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN關(guān)閉按需開啟
          序列化時對Map按照Key進行排序SerializerFeature.MapSortField關(guān)閉SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS關(guān)閉建議關(guān)閉,開啟會影響性能

          序列化fastjson和jackson的特性TestCase見SerializationUseJacksonReplaceFastJsonTest.java

          Annotation

          fastjsonzhu相對于jackson來說注解的功能劃分的并沒有那么細,因此fastjson的一個注解可能等價于jackson多個注解的組合。

          @JSONPOJOBuilder

          指定反序列化時創(chuàng)建java對象使用的build方法,對應(yīng)jackson的@JsonPOJOBuilder。

          @JSONCreator

          指定反序列化時創(chuàng)建java對象使用的構(gòu)造方法,對應(yīng)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 "";

              // 序列化和反序列化時的數(shù)據(jù)格式(日期格式、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 "";

              // 序列化時將字段內(nèi)容直接輸出,不經(jīng)過轉(zhuǎn)義,等價于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 {};

              // 將字段的子屬性映射到父節(jié)點上,等價于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優(yōu)化,jackson無對應(yīng)特性
              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 {};

              // 序列化時是否依據(jù)field字母順序排序,等價于jackson的@JsonPropertyOrder.alphabetic()
              boolean alphabetic() default true;

              // 反序列化多態(tài)類型時,如果根據(jù)其他typeName等方式無法找到正確的子類時,默認使用的子類,等價于jackson的@JsonTypeInfo.defaultImpl()
              Class<?> mappingTo() default Void.class;

              // 反序列化時指定java bean builder類(必須是@JSONPOJOBuilder注解的類),等價于jackson的@JsonDeserialize.builder()
              Class<?> builder() default Void.class;

              // 聲明這個類型的別名,反序列化多態(tài)類型時使用,等價于jackson的@JsonTypeName
              String typeName() default "";

              // 反序列化某個接口或抽象類或父類的子類時指定根據(jù)哪個字段的值和子類的typeName相等來決定具體實現(xiàn)類,等價于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沒有對應(yīng)特性
              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<StringObject>, CloneableSerializableInvocationHandler {

              private final Map<String, Object> map;
              ...
          }
          public class JSONArray extends JSON implements List<Object>, CloneableRandomAccessSerializable {

              private static final long  serialVersionUID = 1L;
              private final List<Object> list;
              protected transient Object relatedArray;
              protected transient Type   componentType;
              ...
          }

          從源碼就可以發(fā)現(xiàn),JSONObject實際是一個Map<String, Object>,而JSONArray實際是一個List<JSONObject>。因此可以將JSONObject類型改為Map<String, Object>,而JSONArray類型改為List<Object>。但是這種方式就會導(dǎo)致上層API出現(xiàn)大量修改,因為缺少了JSONObjectJSONArray提供的多種便利的類型轉(zhuǎn)換方法。如果想要暫時保留JSONObjectJSONArray,此時可以采取一種取巧的方法。

          暫時保留JSONObject & JSONArray的過渡方法

          jackson官方提供了對org.json庫的數(shù)據(jù)類型支持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自己實現(xiàn)jackson對fastjson的數(shù)據(jù)類型的binder。

          larva-zhang/jackson-datatype-fastjson歡迎大家使用或提issues。

          JSONPath

          使用json-path/JsonPath就能輕松替換fastjson的JSONPath,而且功能比fastjson更強大。只需參考JsonProvider SPI使用JacksonJsonProvider替代json-path/JsonPath默認的JsonSmartJsonProvider即可。

          自定義擴展

          自定義Deserializer

          fastjson中實現(xiàn)自定義Deserializer的方法通常是實現(xiàn)ObjectDeserializer接口的deserialze方法

          <T> deserialze(DefaultJSONParser parser, Type type, Object fieldName);

          在jackson中實現(xiàn)自定義Serializer的方法則通常是繼承StdDeserializer抽象類,重寫deserialize方法

          public abstract T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException;

          自定義Serializer

          fastjson中實現(xiàn)自定義Serializer的方法通常是實現(xiàn)ObjectSerializer接口的write方法

          void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException;

          在jackson中實現(xiàn)自定義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。

          往期推薦

          那些在一個公司死磕了5-10年的人,最后都怎么樣了?那些在一個公司死磕了5-10年的人,最后都怎么樣了?

          自從上了 SkyWalking,睡覺真香?。?/p>

          紅包免費送!

          996的大公司和965的小公司,怎么選?網(wǎng)友:錢給夠就行~



          下方二維碼關(guān)注我

          技術(shù)草根堅持分享 編程,算法,架構(gòu)

          看完文章,餓了點外賣,點擊 ??《無門檻外賣優(yōu)惠券,每天免費領(lǐng)!》

          朋友,助攻一把!點個在看!


          瀏覽 113
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无免费码在线 | 躁BBB躁BBB躁BBBBBB日 | 熟妇人妻中文AV无码 | 天堂网黄 | 国产一级a毛一级a看免费视频乱 |