目的
最近兩天在給朋友講解如何使用ajax調用接口時候,我發現我用swagger調用接口返回的long類型的數據最后幾位都變成了0(例如:6974150586715898000),本來是以為sqlite數據庫不支持long類型導致我存進去的數據出了問題,然后我使用接口測試工具調用后發現數據是正確的。然后想到之前聽前端同事說過他們沒有long類型他們使用的字符串來處理的我返回的long類型,那么就思考如何去處理swagger這個問題吧。
這個這兩天才發現,說明我真的好久沒有swagger調用接口了,雖然展示了,然后只是展示了。
解決方案
既然前端同事是通過字符串來處理的,那么我當然也可以轉成字符串之后再返回出去。我是使用的Newtonsoft.Json做解析Json的,所以修改默認的解析
首先我們需要修改Swashbuckle.AspNetCore.Newtonsoft包默認的解析處理DefaultContractResolver,針對long類型做特殊處理
public?class?CustomContractResolver?:?DefaultContractResolver
{///?<summary>///?對長整型做處理///?</summary>///?<param?name="objectType"></param>///?<returns></returns>protected?override?JsonConverter?ResolveContractConverter(Type?objectType){if?(objectType?==?typeof(long)){return?new?JsonConverterLong();}return?base.ResolveContractConverter(objectType);}
}
JsonConverterLong內容如下
///?<summary>
///?Long類型Json序列化重寫
///?在js中傳輸會導致精度丟失,故而在序列化時轉換成字符類型
///?</summary>
public?class?JsonConverterLong?:?JsonConverter
{///?<summary>///?是否可以轉換///?</summary>///?<param?name="objectType"></param>///?<returns></returns>public?override?bool?CanConvert(Type?objectType){return?true;}///?<summary>///?讀json///?</summary>///?<param?name="reader"></param>///?<param?name="objectType"></param>///?<param?name="existingValue"></param>///?<param?name="serializer"></param>///?<returns></returns>public?override?object?ReadJson(JsonReader?reader,?Type?objectType,?object?existingValue,?JsonSerializer?serializer){if?((reader.ValueType?==?null?||?reader.ValueType?==?typeof(long?))?&&?reader.Value?==?null){return?null;}else{_?=?long.TryParse(reader.Value?!=?null???reader.Value.ToString()?:?"",?out?long?value);return?value;}}///?<summary>///?寫json///?</summary>///?<param?name="writer"></param>///?<param?name="value"></param>///?<param?name="serializer"></param>public?override?void?WriteJson(JsonWriter?writer,?object?value,?JsonSerializer?serializer){if?(value?==?null)writer.WriteValue(value);elsewriter.WriteValue(value.ToString());}
}
在上面編寫結束之后我們還需要進行配置也就是設置SerializerSettings
services.AddControllers().AddNewtonsoftJson(options?=>
{//時間格式化options.SerializerSettings.DateFormatString?=?"yyyy-MM-dd?HH:mm:ss";//swagger顯示枚舉options.SerializerSettings.Converters.Add(new?StringEnumConverter());//?設置自定義序列化options.SerializerSettings.ContractResolver?=?new?CustomContractResolver();
});
最后再次使用swagger界面調用返回值已經變成了6974150586715897857,成功解決問題。
總結
關于這個精度丟失的問題這次是第二次遇到了,上次是使用Apifox升級之后就出現了這個問題,然后我還去提了bug,結果是因為更新之后出來了一個兼容bigint的開關并且默認是關閉狀態。