将json反序列化为属性不匹配的对象时引发错误



下面的C#代码:

// See https://aka.ms/new-console-template for more information
using static System.Console;
using System.Text.Json;
List<Person> source = new List<Person>();
using (StreamReader r = new StreamReader("data.json"))
{
string json = r.ReadToEnd();
source = JsonSerializer.Deserialize<List<Person>>(json);
foreach (Person person in source)
{
WriteLine(person.Id);
}

}
public class Person
{    
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string City { get; set; }
}

json文件:

[
{
"Id": 1,
"Firstname": "Hello",
"Lastname": "World",
"City": "New York"
},
{
"Id": 2,
"Firstname": "Foo",
"Lastname": "Bar",
"City": "Phoenix"
}
]

当json文件中的person的属性与C#代码中的person类的属性不匹配时,我希望引发并捕获一个错误——这可能吗?

您可以处理与指定对象中相应属性不匹配的任何属性。

这被称为JSON溢出(JSON中的所有其他属性都将存储在Dictionary中(,它使用JsonExtensionData属性工作。

只需在您的对象中声明另一个属性:

public class Person
{    
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string City { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? OtherData { get; set; }
}

这样,如果您得到一个具有额外属性或名称中有拼写错误的属性的JSON,如:

{
"Id": 1,
"Firstname": "Hello",
"lastNam": "World",
"City": "New York",
"Age": "32"
}

您将在OtherProperties字典中获得反序列化的对象,并按属性名称进行索引。在这种情况下,您将在字典中获得两个项目:AgelastNam,它们各自的值为JsonElements。

通过这种方式,您可以检查任何对象字典中是否存在元素,并抛出错误。在您的示例中并使用linq:

if(source.Any(p => p.OtherData != null && p.OtherData.Any())) {
throw new Exception("JSON contains invalid or unexpected properties");
}

本文中的更多详细信息:https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-handle-overflow?pivots=dotnet-6-0

除了反序列化后选项之外,为了通过定义必须存在(必需(并且必须具有特定类型和值的属性来正确验证JSON,我建议您在反序列化之前使用JSON模式来预验证JSON输入。

通过这种方式,您可以声明一个模式,如:

{
type: "array",
minItems: 1,
items: {
type: "object",
properties: {
Id: { type: "number" },
Firstname: { type: "string" },
Lastname: { type: "string" },
City: { type: "string" }
},
required: [ "Id", "Firstname", "Lastname", "City" ],
additionalProperties: false
}
}

例如,上面的这个模式定义JSON必须是一个至少有一个项的对象数组,并且这些项必须具有所有四个属性:类型为number的Id和类型为string的FistnameLastnameCity,没有其他属性。

下面是一篇关于如何在C#中实现它的文章:https://endjin.com/blog/2021/05/csharp-serialization-with-system-text-json-schema

最新更新