.NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法
行為不一致
.NET Core 3.0 新出了個(gè)內(nèi)置的 JSON 庫(kù), 全名叫做尼古拉斯?System.Text.Json?- 性能更高占用內(nèi)存更少這都不是事...
對(duì)我來(lái)說(shuō), 很多或大或小的項(xiàng)目能少個(gè)第三方依賴項(xiàng), 還能規(guī)避多個(gè)依賴項(xiàng)的依賴 Newtonsoft.Json 版本不一致的問(wèn)題, 是件極美的事情.
但是, 結(jié)果總不是不如預(yù)期那么簡(jiǎn)單和美好, 簡(jiǎn)單測(cè)試了下, 有一些跟?Newtonsoft.Json?行為不一致的地方, 代碼如下:
using Microsoft.VisualStudio.TestTools.UnitTesting;namespace UnitTestProject3 {[TestClass]public class TestJsonDiff{[TestMethod][Description(description: "測(cè)試數(shù)字序列化")]public void TestNumber(){object jsonObject = new { number = 123.456 };string aJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(value: jsonObject);string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject);Assert.AreEqual(expected: aJsonString, actual: bJsonString, message: "測(cè)試數(shù)字序列化失敗");}[TestMethod][Description(description: "測(cè)試英文序列化")]public void TestEnglish(){object jsonObject = new { english = "bla bla" };string aJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(value: jsonObject);string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject);Assert.AreEqual(expected: aJsonString, actual: bJsonString, message: "測(cè)試英文序列化失敗");}[TestMethod][Description(description: "測(cè)試中文序列化")]public void TestChinese(){object jsonObject = new { chinese = "灰長(zhǎng)標(biāo)準(zhǔn)的布咚發(fā)" };string aJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(value: jsonObject);string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject);Assert.AreEqual(expected: aJsonString, actual: bJsonString, message: "測(cè)試中文序列化失敗");}[TestMethod][Description(description: "測(cè)試英文符號(hào)")]public void TestEnglishSymbol(){object jsonObject = new { symbol = @"~`!@#$%^&*()_-+={}[]:;'<>,.?/ " };string aJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(value: jsonObject);string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject);Assert.AreEqual(expected: aJsonString, actual: bJsonString, message: "測(cè)試英文符號(hào)失敗");}[TestMethod][Description(description: "測(cè)試中文符號(hào)")]public void TestChineseSymbol(){object jsonObject = new { chinese_symbol = @"~·@#¥%……&*()—-+={}【】;:“”‘’《》,。?、" };string aJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(value: jsonObject);string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject);Assert.AreEqual(expected: aJsonString, actual: bJsonString, message: "測(cè)試中文符號(hào)失敗");}} }先來(lái)看看總體的測(cè)試結(jié)果:
這是 VS 顯示的結(jié)果
這是執(zhí)行?dotnet test?命令行顯示的結(jié)果
這個(gè)時(shí)候需要配個(gè)圖
那么問(wèn)題來(lái)了,?國(guó)慶去哪玩比較好呢, 我是誰(shuí)? 這是哪? 發(fā)生了什么?
解決辦法
解決中文會(huì)被 Unicode 編碼的問(wèn)題
這個(gè)問(wèn)題是在博客園里找到的一種答案:?.NET Core 3.0 中使用 System.Text.Json 序列化中文時(shí)的編碼問(wèn)題
[TestMethod] [Description(description: "測(cè)試中文序列化")] public void TestChinese() {object jsonObject = new { chinese = "灰長(zhǎng)標(biāo)準(zhǔn)的布咚發(fā)" };string aJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(value: jsonObject);string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject,options: new System.Text.Json.JsonSerializerOptions{Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(allowedRanges: UnicodeRanges.All)});Assert.AreEqual(expected: aJsonString, actual: bJsonString, message: "測(cè)試中文序列化失敗"); }關(guān)鍵在于序列化配置加了一句
new System.Text.Json.JsonSerializerOptions {Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(allowedRanges: UnicodeRanges.All) }但是一些符號(hào)被轉(zhuǎn)義的問(wèn)題還是不管用, 尋思了一上午暫時(shí)沒(méi)找到答案...
至于什么時(shí)候修復(fù)此類問(wèn)題,
我去源碼?corefx?溜個(gè)一圈, 暫時(shí)的發(fā)現(xiàn)是歸到了 .NET Core 3.1 和 5.0 的開發(fā)時(shí)間線里...后面回來(lái)發(fā)現(xiàn)這不應(yīng)該啊
但是...難道就這樣了?
懷著受傷的核桃心, 中午又吃了3只大閘蟹...
詭異的是新建 ASP.NET Core API (.NET Core 3.0) 輸出的 JSON 中文和轉(zhuǎn)義字符都是正常, 如圖:
說(shuō)明一定是我們打開的方式不對(duì)...回娘家找源碼, 尋尋匿匿最后發(fā)現(xiàn)這么一句
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters. jsonSerializerOptions = jsonSerializerOptions.Copy(JavaScriptEncoder.UnsafeRelaxedJsonEscaping);less strict?? 那對(duì)照的意思是 Newtonsoft.Json 一直使用的就是非嚴(yán)格模式咯, 而我們習(xí)慣使用的也是這種模式.
那么改下, 還報(bào)錯(cuò)的單元測(cè)試都加上配置?JavaScriptEncoder.UnsafeRelaxedJsonEscaping, 果然測(cè)試結(jié)果順眼多了. 連上面的?UnicodeRanges.All?都不需要配置了.
string bJsonString = System.Text.Json.JsonSerializer.Serialize(value: jsonObject,options: new System.Text.Json.JsonSerializerOptions{Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping});又整明白一個(gè)問(wèn)題, 開森...
總結(jié)
以上是生活随笔為你收集整理的.NET Core 3.0 System.Text.Json 和 Newtonsoft.Json 行为不一致问题及解决办法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 知道的越多,越感觉自己渺小
- 下一篇: WinForms项目升级.Net Cor