我尝试将JsonPropertyName与System.Text.Json中的JsonConstuctor属性结合使用,以将json序列化添加到现有库中。
每个类型都有一个构造函数,它主要匹配只读字段(和/或get only属性)。问题是名称并不总是匹配,我不想重命名公共成员的属性/参数。
所以一个class/struct可能看起来像这样:
public struct Person
{
public Person(string Name)
{
FirstName = Name
}
public string FirstName { get; }
}
字符串
我本以为这会奏效:
public struct Person
{
[JsonConstructor]
public Person(string Name)
{
FirstName = Name
}
[JsonPropertyName("Name")]
public string FirstName { get; }
}
型
json输出看起来正确
{
"Name": "Joe"
}
型
但在执行异常化时,会抛出以下错误。
“类型”Person“上的对象化构造函数中的每个参数必须绑定到对象化时的对象属性或字段。每个参数名称必须与对象上的属性或字段匹配。匹配可以不区分大小写。”
当我写这篇文章的时候,我现在在想,[JsonConstructor]属性并没有强制解析器调用构造函数,并将JSON键与参数名匹配,而是使用构造函数中的名称来只设置那些在名称上匹配的属性。在任何情况下,是否有方法不修改Person结构(理想情况下使用属性)来支持System.Text.Json序列化?
4条答案
按热度按时间mpbci0fu1#
我从来没有见过System.Text.Json.JsonConstructor正常工作,当我看到一个例子,我会让你知道。所以我建议你发送电子邮件给微软,感谢他们的一个惊人的解析器,并使用Newtonsoft.Json
字符串
eagi6jfj2#
如果你能够改变现有的库,那么使用C# 9,你可以添加一个
private init;
并执行以下操作:字符串
您需要
[JsonInclude]
才能允许解析器使用private init
。这不会改变结构体的公共API,从您的问题来看,您可能对此没有意见。
在C# 9之前,您可以使用
private set;
,但这会在内部打开API。guz6ccqo3#
如果你将这个构造函数参数从
Name
重命名为firstName
,那么使用System.Text.Json
就可以正常工作。(
FirstName
* 也可以,但camel case对于参数来说更常见。这样做,构造函数参数
firstName
匹配FirstName
属性的名称,就像异常消息中提到的那样。每个参数名称必须与对象的属性或字段匹配。匹配可以不区分大小写。
个字符
的数据
zu0ti5jz4#
你可以使用json构造函数并使用反射中的属性或字段名称,或者使用JsonParameterName属性而不使用json构造函数,你不能两者兼而有之。也许.net 9允许它,但当你查看源代码生成器时,它不允许,因为它在属性名称上使用反射。要亲自查看,右键单击ToDoJsonContext并选择“go to definition.”,然后查看它期望如何调用构造函数
正如Yits提到的,删除json构造函数(意味着你需要支持无参数构造函数)。
下面是一个小的测试应用程序:
字符串
我还设置了我的项目来支持AOT:
型
我使用以下发布设置在发布模式和AoT中运行它:x1c 0d1x
工作起来很有魅力:
{“a”:378268935,“B”:“test a class”} [{“a”:1,“B”:“test json serialization”},{“a”:2,“B”:“test call constructor”}]按enter退出