日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

记一次fastjson转jackson的生产事故

發布時間:2025/3/20 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记一次fastjson转jackson的生产事故 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

之前暴露出fastjson存在漏洞,雖然后期fastjson團隊對于相關漏洞有修復,但是為了確保服務和數據的安全性,公司還是決定所有項目棄用fastjson,改用jackson。因為之前項目很多地方都運用了fastjson,改起來算是一個大工程了,有些地方沒注意可能就會導致出錯,這不,在換了以后的確遇到了問題。
客戶需要下單,具體邏輯我就不講了,里面有一個json字符串轉對象的操作,然后獲取對象中的data屬性用于后續操作。用過fastjson的伙伴都知道可以使用JSON.parseObject(String content)將json字符串轉換為對象:

String jsonString="{"data":"testFastjson"}" String body = String.valueOf(JSON.parseObject(jsonString).get("data"));

公司代碼不便公開,在這里簡要的進行了更改。通過程序調試我們可以看到,最終body的值為"testFastjson",為正確的值。

然后在使用jackson替換fastjson,需要實現同樣的功能,我們使用了jackson提供的new ObjectMapper().readValue(String content, Class valueType)。因為對jackson的用法不是很清楚,然后就直接運用了,代碼如下:

String jsonString="{"data":"testFastjson"}" String body = String.valueOf(new ObjectMapper().readValue(jsonString, ObjectNode.class).get("data"))

同樣debug以后查看轉換后的body值,發現body的值為"“testFastjson”":

大家有沒有發現有什么不一樣?沒錯,jackson最后竟然的數據是帶""的。what?除了問題當然是需要解決,不僅要解決,還要搞明白這里為什么會是這個樣子。本著懷疑的態度,我debug進了jackson相關方法的readValue源碼進行查看:

public <T> T readValue(String content, Class<T> valueType)throws JsonProcessingException, JsonMappingException{_assertNotNull("content", content);return readValue(content, _typeFactory.constructType(valueType));}

繼續進去:

public <T> T readValue(String content, JavaType valueType)throws JsonProcessingException, JsonMappingException{_assertNotNull("content", content);try { // since 2.10 remove "impossible" IOException as per [databind#1675]return (T) _readMapAndClose(_jsonFactory.createParser(content), valueType);} catch (JsonProcessingException e) {throw e;} catch (IOException e) { // shouldn't really happen but being declared need tothrow JsonMappingException.fromUnexpectedIOE(e);}}

重點來了,里面調用的是_readMapAndClose(JsonParser p0, JavaType valueType)方法,我們繼續進去;

protected Object _readMapAndClose(JsonParser p0, JavaType valueType)throws IOException{try (JsonParser p = p0) {Object result;JsonToken t = _initForReading(p, valueType);final DeserializationConfig cfg = getDeserializationConfig();final DeserializationContext ctxt = createDeserializationContext(p, cfg);if (t == JsonToken.VALUE_NULL) {// Ask JsonDeserializer what 'null value' to use:result = _findRootDeserializer(ctxt, valueType).getNullValue(ctxt);} else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) {result = null;} else {JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);if (cfg.useRootWrapping()) {result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);} else {//走這里result = deser.deserialize(p, ctxt);}ctxt.checkUnresolvedObjectId();}if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {_verifyNoTrailingTokens(p, ctxt, valueType);}return result;}}

我們看一下最后的返回結果:

發現返回的結果是一個LinkedHashMap,其中的key是data,value是"testFastJson":

key:"data" value:""testFastJson""

到這里我們發現了,如果以ObjectMapper作為返回類的話,它的本質是最終轉換成鍵值對的LinkedHashMap,且key是屬性名稱,值是屬性對應的值但是加上了雙引號,這就是問題的本質了,然后我們再依據這個key去獲取值的話,那就肯定是帶引號的值了:

所以不對,最終導致問題的出現。在這里記錄一下以防大家跟我有同樣問題的伙伴提個醒。如果大家想要獲取正確的數據,如果已經知道需要轉換的結構,大家可以先自定義個具體的類別,將ObjectMapper.class替換成對應的類別即可,如果不知道需要具體轉換的類別,可以在轉換完成之后,調用對應的asText()方法即可獲得正確的值:

String jsonString="{"data":"testFastjson"}" String body = new ObjectMapper().readValue(jsonString, ObjectNode.class).get("data").asText()

我么看一下改完之后獲取的情況:

至此問題得到解決。雖然看起來很簡單,但是在實際操作中還是需要注意。在這里雖然只是多了一個引號,但是如果不及時發現處理將會導致大量訂單的失敗,會帶來很大的損失。記錄此次的問題過程,給自己一個提醒,以后小問題也需要好好的對待。

總結

以上是生活随笔為你收集整理的记一次fastjson转jackson的生产事故的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。