讀者 Galaxy952 分享一則實際經驗:JSON 反序列化時,若出現對映型別上沒有的屬性一般都會選擇無視,但某些資安政策認為 JSON 反序列化容忍未被定義的屬性是一種風險。故詢問 .NET 要如何偵測 JSON 有多餘的屬性參數並回傳錯誤。

舉例來說,若我們的物件有 Id 及 Name 兩個屬性,若傳入 JSON 內容如下(多了 NoSuchProp),程式必須拋出例外並拒絕反序列化:

{
    "Id": 32767,
    "Name": "Jeffrey",
    "NoSuchProp": "No mapping for this property"
}

先寫一小段程式驗證標準行為,分別用 Json.NET 跟 System.Text.Json 反序化這段多了 NoSuchProp 的 JSON 內容,二者都會無視 NoSuchProp 完成轉換。

using Newtonsoft.Json;

var json = @"{
    ""Id"": 32767,
    ""Name"": ""Jeffrey"",
    ""NoSuchProp"": ""No mapping for this property""
}";

try
{
    var userJsonNet = JsonConvert.DeserializeObject<User>(json);
    Console.WriteLine("Json.NET deserialized the object successfully");
}
catch (Exception ex)
{
    Console.WriteLine("Json.NET ERROR-" + ex.Message);
}
try
{
    var userTextJson = System.Text.Json.JsonSerializer.Deserialize<User>(json);
    Console.WriteLine("System.Text.Json deserialized the object successfully");
}
catch (Exception ex)
{
    Console.WriteLine("System.Text.Json ERROR-" + ex.Message);
}

class User {
    public int Id {get; set;}
    public string Name {get; set;}   
}

要解決這個問題,Json.NET 可在 JsonSerializationOptions 加上 MissingMemberHandling.Error 設定;System.Text.Json 則是在 .NET 8 開始加入 JsonUnmappedMemberHandlingAttribute 標註物件不允許 JSON 包含未對映屬性。(若尚末升級 .NET 6 ,可考慮自己實作)

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

var json = @"{
    ""Id"": 32767,
    ""Name"": ""Jeffrey"",
    ""NoSuchProp"": ""No mapping for this property""
}";

try
{
    var userJsonNet = JsonConvert.DeserializeObject<User>(json, new JsonSerializerSettings {
        MissingMemberHandling = MissingMemberHandling.Error
    });
    Console.WriteLine("Json.NET deserialized the object successfully");
}
catch (Exception ex)
{
    Console.WriteLine("Json.NET ERROR-" + ex.Message);
}
try
{
    var userTextJson = System.Text.Json.JsonSerializer.Deserialize<User>(json);
    Console.WriteLine("System.Text.Json deserialized the object successfully");
}
catch (Exception ex)
{
    Console.WriteLine("System.Text.Json ERROR-" + ex.Message);
}

[JsonUnmappedMemberHandling(JsonUnmappedMemberHandling.Disallow)]
class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

修改後,Json.NET 及 System.Text.Json 便會因 JSON 多了 NoSuchProp 無法反序列化,搞定。

Guidelines on avoiding unmapped properties in JSON using Json.NET and System.Text.Json.


Comments

# by Galaxy952

謝謝黑大的詳解,我再來去修改程式測試。

Post a comment