C# System.Text.Json 詳細教學和程式碼示範

目錄:

基本使用方式

JSON 範例檔案:
    
{
  "name": "Ruyut",
  "Email": "a@ruyut.com",
  "phone": "0987654321",
  "age": 100
}
    

範例物件:
    
public class JsonExample
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public int Age { get; set; }
}
    

將物件內容變為 JSON 格式(序列化)

    
var jsonExample = new JsonExample
{
    Name = "Ruyut",
    Email = "a@ruyut.com",
    Phone = "0987654321",
    Age = 100,
};

string jsonString = JsonSerializer.Serialize(jsonExample);
Console.Write(jsonString);
// {"Name":"Ruyut","Email":"a@ruyut.com","Phone":"0987654321","Age":100}
    

讀取 JSON 內容到物件中(反序列化)

    
string jsonString = File.ReadAllText("example.json"); // 讀取 JSON 資料
JsonExample? jsonExample = JsonSerializer.Deserialize<JsonExample>(jsonString);
    

JSON 陣列、清單的轉換方式

將物件內容變為 JSON 格式(序列化)

    
var list = new JsonExample[]
{
    new JsonExample()
    {
        Name = "Ruyut",
        Email = "a@ruyut.com",
        Phone = "0987654321",
        Age = 100,
    },
    new JsonExample()
    {
        Name = "test",
        Email = "test@ruyut.com",
        Phone = "0987654321",
        Age = 50,
    },
};
string jsonString = JsonSerializer.Serialize(list);
Console.Write(jsonString);
// [{"Name":"Ruyut","Email":"a@ruyut.com","Phone":"0987654321","Age":100},{"Name":"test","Email":"test@ruyut.com","Phone":"0987654321","Age":50}]
    

讀取 JSON 內容到物件中(反序列化)

    
[
  {
    "Name": "Ruyut",
    "Email": "a@ruyut.com",
    "Phone": "0987654321",
    "Age": 100
  },
  {
    "Name": "test",
    "Email": "test@ruyut.com",
    "Phone": "0987654321",
    "Age": 50
  }
]
    

    
string jsonString = File.ReadAllText("example.json"); // 讀取 JSON 資料
List<JsonExample>? jsonExample = JsonSerializer.Deserialize<List<JsonExample>>(jsonString);

    

自訂屬性名稱

如果物件中的屬性名稱和 JSON 需要不一樣時,可以使用 JsonPropertyName 來自訂名稱
    
public class JsonExample
{
    public string Name { get; set; }
    public string Email { get; set; }
    [JsonPropertyName("p")] public string Phone { get; set; } // 自訂名稱為 p
    public int Age { get; set; }
}
    

輸出 JSON 支援中文

筆者在測試時如果來源 JSON 內容有中文可以被正常讀取,但是物件內的中文在輸出時會變成 Unicode 字元...
    
var jsonExample = new JsonExample
{
    Name = "筆者",
};

string jsonString = JsonSerializer.Serialize(jsonExample);
Console.Write(jsonString); // {"Name":"\u7B46\u8005"}
    

研究了一下才發現原來一切都是為了安全啊!包含常用的 HTML 字元都會被轉掉,例如 > < &,如果要正確輸出為中文和那些符號則要加上 UnsafeRelaxedJsonEscaping
    
var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};

var jsonExample = new JsonExample
{
    Name = "筆者",
};

string jsonString = JsonSerializer.Serialize(jsonExample, options);
Console.Write(jsonString); // {"Name":"筆者"}
    

忽略欄位

在類別中使用 JsonIgnore 可以忽略該欄位
    
public class JsonExample
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    [JsonIgnore] public int Age { get; set; } // 忽略 Age
}
    

調整輸出 JSON 的順序

在將物件序列化為 JSON 的時候預設是依照物件中的順序由上到下輸出,如果要自訂順序可以使用 JsonPropertyOrder,經過測試順序如下
  1. 負數優先(越小越優先)
  2. 0 就是依照預設(和沒有使用 JsonPropertyOrder 的優先程度一樣,從上到下)
  3. 大於 0 的數就是負數、預設、0 排完後依照數字順序由小到大
    
public class JsonExample
{
    [JsonPropertyOrder(1)] public string Name { get; set; }
    public string Email { get; set; }
    [JsonPropertyOrder(-2)] public string Phone { get; set; }
    [JsonPropertyOrder(-1)] public int Age { get; set; }
    // 順序: Phone, Age, Email, Name
}
    

格式化輸出 JSON (增加換行)

預設在輸出 JSON 時內容會省略多餘的換行和空白,以最短的形式輸出 JSON 內容。如果想要以比較方便人類閱讀、包含換行的方式輸出的話可以使用下面的選項:
    
var options = new JsonSerializerOptions
{
    WriteIndented = true
};

var jsonExample = new JsonExample
{
    Name = "筆者",
};

string jsonString = JsonSerializer.Serialize(jsonExample, options);
Console.Write(jsonString);
    

不區分大小寫

System.Text.Json 預設會區分大小寫,在上面的範例中 JSON Key 的部分都是使用大寫作示範,如果大小寫不符合時資料就不會被塞進去,調整為不區分大小寫的方式如下:
    
var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true, // 不區分大小寫
};

string jsonString = File.ReadAllText("example.json"); // 讀取 JSON 資料
JsonExample? jsonExample = JsonSerializer.Deserialize<JsonExample>(jsonString, options);
    

忽略結尾逗號

預設不允許結尾逗號,如果在 JSON 文字中遇到結尾逗號就會拋出錯誤

{
  "name": "Ruyut",
  "Email": "a@ruyut.com",
  "Phone": "0987654321",
  "Age": 100,
}
    

忽略結尾逗號:
    
var options = new JsonSerializerOptions
{
    AllowTrailingCommas = true, // 忽略結尾逗號
};

string jsonString = File.ReadAllText("example.json"); // 讀取 JSON 資料
JsonExample? jsonExample = JsonSerializer.Deserialize<JsonExample>(jsonString, options);
    

忽略註解

預設不允許註解,如果在 JSON 文字中遇到註解(// 和 /* */)就會拋出錯誤
    
{
  "name": "Ruyut",
  "Email": "a@ruyut.com",
  "Phone": "0987654321" /* test */,
  "Age": 100 //test
}
    

忽略 JSON 註解:
    
var options = new JsonSerializerOptions
{
    ReadCommentHandling = JsonCommentHandling.Skip, // 忽略註解
};

string jsonString = File.ReadAllText("example.json"); // 讀取 JSON 資料
JsonExample? jsonExample = JsonSerializer.Deserialize<JsonExample>(jsonString, options);
    

調整最大深度

System.Text.Json 在 JSON 的最大深度預設為 64 (在 ASP.NET Core 中預設為 32)
    
var options = new JsonSerializerOptions
{
    MaxDepth = 100, // 最大深度設為 100
};
    



參考資料:
System.Text.Json

留言