最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中Newtonsoft.Json 到 System.Text.Json 遷移避坑指南

 更新時間:2026年03月05日 09:09:16   作者:xyy123  
本文主要介紹了C#中Newtonsoft.Json 到 System.Text.Json 遷移避坑指南,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1. 核心設(shè)計哲學差異

在進行代碼遷移前,必須牢記這兩個庫在底層設(shè)計哲學上的根本分歧,這是幾乎所有反序列化報錯的根源:

  • Newtonsoft.Json (主打兼容與靈活) :它非常寬容,會盡最大努力去猜測你的意圖,在底層默默幫你做各種隱式的類型轉(zhuǎn)換和容錯處理。
  • System.Text.Json (主打性能與安全) :微軟為了追求極致的執(zhí)行效率而原生打造。它極其嚴格,要求 JSON 數(shù)據(jù)結(jié)構(gòu)和 C# 模型“嚴絲合縫”,絕不會越界替你做任何類型轉(zhuǎn)換。

2. 基礎(chǔ)特性與配置替換對照表

場景Newtonsoft.Json (舊)System.Text.Json (新)遷移備注
指定 JSON 鍵名[JsonProperty("name")][JsonPropertyName("name")]必須逐個替換。
忽略某字段[JsonIgnore][JsonIgnore]基本一致。
忽略空值 (Null)NullValueHandling.Ignore全局 Options: DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull推薦在全局 JsonSerializerOptions 中統(tǒng)一配置,減少序列化體積。
忽略默認值DefaultValueHandling.Ignore[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]新版將其合并到了 JsonIgnore 特性中。

3. 四大高頻“踩坑”重災(zāi)區(qū)及標準解決方案

?? 坑一:大小寫嚴格敏感 (Case Sensitivity)

問題描述:很多第三方 API 返回的小駝峰命名(如 userProfile),而 C# 模型是大駝峰命名(如 UserProfile)。老版能完美自動映射,新版只要大小寫不一致,直接反序列化為 null。

解決方案:在反序列化時,務(wù)必全局傳入配置允許忽略大小寫:

var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var result = JsonSerializer.Deserialize<MyModel>(jsonString, options);

?? 坑二:基礎(chǔ)類型嚴格匹配(數(shù)字與字符串的鴻溝)

問題描述:對接外部不可控 API 時經(jīng)常遇到格式不規(guī)范的數(shù)據(jù)。比如 ID 字段有時是數(shù)字 ("id": 123),有時是字符串 ("id": "A-123");金額字段有時返回字符串 ("price": "19.99"),甚至用空字符串表示無數(shù)據(jù) ("discount": "")。

新版只要遇到 JSON 節(jié)點類型與 C# 聲明類型(如 stringint)不匹配,會直接拋出 JsonException 崩潰。

解決方案:不要指望內(nèi)置配置項能完美兜底(尤其是處理空字符串),建議直接封裝自定義 JsonConverter

??? 通用工具 1:數(shù)字安全轉(zhuǎn)字符串轉(zhuǎn)換器 (NumberToStringConverter)

用途:當 C# 模型定義為 string Id,但外部 JSON 傳入的是數(shù)字 123 時,自動將其轉(zhuǎn)換為 "123" 且不報錯。

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace YourNamespace.Helpers 
{
    public class NumberToStringConverter : JsonConverter<string?>
    {
        public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.Number) return reader.GetInt64().ToString(); 
            if (reader.TokenType == JsonTokenType.String) return reader.GetString();
            return null;
        }

        public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
        {
            if (value == null) writer.WriteNullValue();
            else writer.WriteStringValue(value);
        }
    }
}
// 實體類使用方式:[JsonConverter(typeof(NumberToStringConverter))]

??? 通用工具 2:字符串安全轉(zhuǎn)可空金額轉(zhuǎn)換器 (StringToDecimalConverter)

用途:當 C# 模型定義為 decimal? Price,但 JSON 傳入的是 "19.99" 或者是代表無值的空字符串 "" 時,安全地將其轉(zhuǎn)換為 decimalnull。

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace YourNamespace.Helpers 
{
    // 注意:泛型必須與屬性類型完全一致(此處為可空類型 decimal?)
    public class StringToDecimalConverter : JsonConverter<decimal?>
    {
        public override decimal? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.Number) return reader.GetDecimal();
            if (reader.TokenType == JsonTokenType.String)
            {
                string? strValue = reader.GetString();
                // 很多老舊 API 喜歡用空字符串代表沒有值,安全處理為 null
                if (string.IsNullOrWhiteSpace(strValue)) return null;
                if (decimal.TryParse(strValue, out decimal result)) return result;
            }
            return null;
        }

        public override void Write(Utf8JsonWriter writer, decimal? value, JsonSerializerOptions options)
        {
            // 序列化時,可根據(jù)對接方 API 的偏好決定是否轉(zhuǎn)回字符串
            if (value.HasValue) writer.WriteStringValue(value.Value.ToString("0.00"));
            else writer.WriteNullValue();
        }
    }
}
// 實體類使用方式:[JsonConverter(typeof(StringToDecimalConverter))]
// 警告:此轉(zhuǎn)換器必須配合 public decimal? Price { get; set; } 使用!不可用于非空 decimal。

?? 坑三:動態(tài)類型object的解析陷阱

問題描述:當模型中存在 public object Value { get; set; }(例如用于接收不確定結(jié)構(gòu)的數(shù)據(jù)、擴展字段 metadata 等),老版會猜測并轉(zhuǎn)化為 string, int 等具體 C# 基礎(chǔ)類型。而新版會統(tǒng)一將其解析為 JsonElement 結(jié)構(gòu)體。

危險操作:任何試圖將反序列化后的 object 強轉(zhuǎn)回基礎(chǔ)類型的操作都會導致運行時崩潰!

  • ? string val = (string)model.Value; -> 拋出 InvalidCastException
  • ? if (model.Value is string s) -> 永遠為 false
  • ? string val = model.Value as string; -> 永遠返回 null

安全的操作規(guī)范(提取真實數(shù)據(jù))

  1. 純中轉(zhuǎn)/序列化/拼接場景(最穩(wěn)妥) :利用 Convert.ToString() 提取字面量。

    // 完美應(yīng)對 JsonElement。
    // 配合 InvariantCulture 防止部署在不同國家服務(wù)器時,小數(shù)點被轉(zhuǎn)換成逗號的問題。
    string safeStringValue = Convert.ToString(model.Value, CultureInfo.InvariantCulture)!;
    
  2. 業(yè)務(wù)邏輯需嚴格執(zhí)行類型判斷:通過檢查 JsonElement.ValueKind。

    if (model.Value is JsonElement element)
    {
        if (element.ValueKind == JsonValueKind.String) 
            string s = element.GetString();
        else if (element.ValueKind == JsonValueKind.Number) 
            decimal d = element.GetDecimal();
    }
    

?? 坑四:字段 (Fields) 被靜默忽略

問題描述:老版會自動序列化和反序列化 public string name; 這種公開的字段 (Fields)。新版默認只處理屬性 (Properties) ,即帶有 { get; set; } 的成員,對字段直接靜默忽略,不報錯但數(shù)據(jù)會全部丟失。

解決方案

  1. 最佳實踐:將實體類的成員強制重構(gòu)為標準屬性 { get; set; }。

  2. 兼容方案:若存在大量歷史代碼難以修改,需在全局 Options 中顯式開啟:

    var options = new JsonSerializerOptions { IncludeFields = true };
    

4. 遷移與調(diào)試的黃金法則

在未來遇到 System.Text.Json 拋出異?;蚍葱蛄谢?null 時,請嚴格遵循以下排查步驟:

  1. 絕不盲猜數(shù)據(jù)結(jié)構(gòu):不要依賴 API 文檔。務(wù)必將 response.Content.ReadAsStreamAsync() 臨時替換為 ReadAsStringAsync(),把原始 JSON 字符串完整打印到日志中,肉眼確認真實的層級和數(shù)據(jù)格式。
  2. 檢查大小寫配置:確認代碼中是否遺漏了 PropertyNameCaseInsensitive = true 的配置。
  3. 檢查類型嚴格性:排查 JSON 里的 "123" 和 C# 里的 int 是否發(fā)生了直接碰撞,若有,必須引入 Converter。
  4. 檢查轉(zhuǎn)換器泛型匹配:貼在可空類型屬性上的轉(zhuǎn)換器,其繼承的基類絕對不能是非空類型(如 JsonConverter<decimal?> 絕不能用于 decimal 屬性),必須分毫不差。

到此這篇關(guān)于C#中Newtonsoft.Json 到 System.Text.Json 遷移避坑指南的文章就介紹到這了,更多相關(guān)C#中Newtonsoft.Json到System.Text.Json 遷移內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用C#代碼實現(xiàn)將圖片插入到Excel中

    使用C#代碼實現(xiàn)將圖片插入到Excel中

    圖片是一種直觀、高效的信息表達方式,在實際工作中,常常需要在 Excel 報告中插入圖片,本文將以 Spire.XLS for .NET 為例,介紹如何使用 C# 和 VB.NET 在 Excel 文檔中插入圖片,有需要的小伙伴可以了解下
    2026-01-01
  • C#日歷樣式的下拉式計算器實例講解

    C#日歷樣式的下拉式計算器實例講解

    如果我們正在做一個類似于庫存控制和計費系統(tǒng)的項目,有些部分可能必須手動計算數(shù)值。因此,用戶就不得不使用計算器得到結(jié)果,再填入到輸入字段中,或者在工作窗口上單獨打開一個計算器窗口??傊?,各種不便和麻煩。
    2015-09-09
  • C#.NET?ConcurrentBag<T>?設(shè)計原理與使用場景

    C#.NET?ConcurrentBag<T>?設(shè)計原理與使用場景

    ConcurrentBag<T>?是System.Collections.Concurrent?命名空間下的線程安全的無序集合,本文就來詳細的介紹一下C#.NET?ConcurrentBag<T>?原理與使用,感興趣的可以了解一下
    2026-01-01
  • C#使用Free?Spire.PDF進行PDF打印的實現(xiàn)方案

    C#使用Free?Spire.PDF進行PDF打印的實現(xiàn)方案

    在現(xiàn)代應(yīng)用開發(fā)中,打印?PDF?文件是一個常見需求,C#?提供了多種庫來支持這一功能,其中?Free?Spire.PDF?for?.NET?是一個不錯的選擇,本文將深入解析如何使用?Free?Spire.PDF?進行?PDF?打印,需要的朋友可以參考下
    2025-08-08
  • automation服務(wù)器不能創(chuàng)建對象 解決方法

    automation服務(wù)器不能創(chuàng)建對象 解決方法

    本文主要介紹如何解決“automation服務(wù)器不能創(chuàng)建對象”錯誤,從而解決Visual Studio.Net不能正常使用的問題,需要的朋友可以參考下。
    2016-06-06
  • C#多線程之取消架構(gòu)介紹

    C#多線程之取消架構(gòu)介紹

    這篇文章介紹了C#多線程之取消架構(gòu),文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • C#借助Spire.XLS?for?.NET實現(xiàn)一鍵移除Excel條件格式

    C#借助Spire.XLS?for?.NET實現(xiàn)一鍵移除Excel條件格式

    在日常開發(fā)中,我們經(jīng)常會遇到需要處理?Excel?文件的場景,本文將介紹如何借助?Spire.XLS?for?.NET?在?C#?中高效地移除這些條件格式,有需要的可以了解下
    2026-03-03
  • C#編程實現(xiàn)向并口設(shè)備發(fā)送指令、獲取并口設(shè)備的狀態(tài)

    C#編程實現(xiàn)向并口設(shè)備發(fā)送指令、獲取并口設(shè)備的狀態(tài)

    這篇文章主要介紹了C#編程實現(xiàn)向并口設(shè)備發(fā)送指令、獲取并口設(shè)備的狀態(tài),本文直接給出實例代碼,需要的朋友可以參考下
    2015-06-06
  • C# 監(jiān)控 Windows 文件夾的方法

    C# 監(jiān)控 Windows 文件夾的方法

    這篇文章主要介紹了C# 監(jiān)控 Windows 文件夾的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • C#使用log4net記錄日志

    C#使用log4net記錄日志

    本文詳細講解了C#使用log4net記錄日志的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-12-12

最新評論

驻马店市| 黄山市| 普陀区| 彝良县| 静海县| 稷山县| 历史| 玉溪市| 元江| 基隆市| 灵山县| 新龙县| 宿州市| 通州区| 安岳县| 哈尔滨市| 兰西县| 巴马| 黄梅县| 诸城市| 蓬溪县| 鹤壁市| 芜湖市| 眉山市| 忻州市| 恩平市| 鄂温| 安福县| 文水县| 西峡县| 乐都县| 青川县| 卓尼县| 南皮县| 石城县| 邢台市| 惠安县| 焦作市| 眉山市| 昆明市| 金塔县|