System.Text.Json 不会反序列化为我的类型,即使我的构造函数实现了每个 属性
System.Text.Json won't deserialize to my type even though my constructor implements every property
我不明白为什么 System.Text.Json 不会将这个简单的 JSON 字符串反序列化为我指定的 .NET 类型。我收到 Each parameter in the deserialization constructor on type 'MenuItem' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive
错误消息,即使我已经映射了每个 属性 — name
、url
和 permissions
— 在我的 MenuItem
构造函数。
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
public class Program
{
public static void Main()
{
try
{
var json = @"
[
{
""name"": ""General Info"",
""url"": ""/Info"",
""permissions"": []
},
{
""name"": ""Settings"",
""url"": ""/Settings"",
""permissions"": [
""Admin""
]
}
]";
Console.WriteLine(json);
var menu = new Menu(json);
Console.WriteLine("Deserialization success");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
public class Menu
{
public Menu(string json)
{
var items = JsonSerializer.Deserialize<List<MenuItem>>(json);
MenuItems = items.AsReadOnly();
}
public IReadOnlyList<MenuItem> MenuItems { get; }
}
public class MenuItem
{
[JsonConstructor]
public MenuItem
(
string name,
string url,
List<Permission> permissions
)
{
this.Name = name;
this.Url = url;
this.Permissions = (permissions ?? new List<Permission>()).AsReadOnly();
}
public string Name { get; }
public string Url { get; }
public IReadOnlyList<Permission> Permissions { get; }
}
public enum Permission
{
Admin,
FinancialReporting
}
谁能告诉我我做错了什么?
我查看了您的 fiddle 并发现了一些问题。 Working fiddle here
System.Text.Json
默认为 case-sensitive (except for web apps)。您可以通过在序列化程序选项中使用 PropertyNamingPolicy = JsonNamingPolicy.CamelCase
或 PropertyNameCaseInsensitive = true
来解决此问题。
第二期概述在Enums as strings
By default, enums are serialized as numbers. To serialize enum names
as strings, use the JsonStringEnumConverter.
您应该添加 JsonSerializerOptions
来解决 (1) 和 (2):
var options = new JsonSerializerOptions
{
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
},
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
var items = JsonSerializer.Deserialize<List<MenuItem>>(json, options);
第三个问题似乎与构造函数中的绑定有关
对于 Permissions
的列表。在构造函数中你定义了一个
List<Permission>
用于权限参数。我收到
除非构造函数参数类型匹配,否则您的问题出错
模型 属性 类型 完全 。所以,我将构造函数更新为
获取 IReadOnlyList<Permission>
并成功反序列化:
[JsonConstructor]
public MenuItem
(
string name,
string url,
IReadOnlyList<Permission> permissions
)
{
this.Name = name;
this.Url = url;
this.Permissions = permissions ?? new List<Permission>().AsReadOnly();
}
或者,您可以将 Permissions
属性 更改为 List<Permission>
。
这个 to a question with a similar problem explains that this is actually a limitation of System.Text.Json
and there is currently an open github issue.
你的 fiddle 的一个工作分支是 demoed here。
我不明白为什么 System.Text.Json 不会将这个简单的 JSON 字符串反序列化为我指定的 .NET 类型。我收到 Each parameter in the deserialization constructor on type 'MenuItem' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive
错误消息,即使我已经映射了每个 属性 — name
、url
和 permissions
— 在我的 MenuItem
构造函数。
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
public class Program
{
public static void Main()
{
try
{
var json = @"
[
{
""name"": ""General Info"",
""url"": ""/Info"",
""permissions"": []
},
{
""name"": ""Settings"",
""url"": ""/Settings"",
""permissions"": [
""Admin""
]
}
]";
Console.WriteLine(json);
var menu = new Menu(json);
Console.WriteLine("Deserialization success");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
public class Menu
{
public Menu(string json)
{
var items = JsonSerializer.Deserialize<List<MenuItem>>(json);
MenuItems = items.AsReadOnly();
}
public IReadOnlyList<MenuItem> MenuItems { get; }
}
public class MenuItem
{
[JsonConstructor]
public MenuItem
(
string name,
string url,
List<Permission> permissions
)
{
this.Name = name;
this.Url = url;
this.Permissions = (permissions ?? new List<Permission>()).AsReadOnly();
}
public string Name { get; }
public string Url { get; }
public IReadOnlyList<Permission> Permissions { get; }
}
public enum Permission
{
Admin,
FinancialReporting
}
谁能告诉我我做错了什么?
我查看了您的 fiddle 并发现了一些问题。 Working fiddle here
System.Text.Json
默认为 case-sensitive (except for web apps)。您可以通过在序列化程序选项中使用PropertyNamingPolicy = JsonNamingPolicy.CamelCase
或PropertyNameCaseInsensitive = true
来解决此问题。第二期概述在Enums as strings
By default, enums are serialized as numbers. To serialize enum names as strings, use the JsonStringEnumConverter.
您应该添加
JsonSerializerOptions
来解决 (1) 和 (2):var options = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; var items = JsonSerializer.Deserialize<List<MenuItem>>(json, options);
第三个问题似乎与构造函数中的绑定有关 对于
Permissions
的列表。在构造函数中你定义了一个List<Permission>
用于权限参数。我收到 除非构造函数参数类型匹配,否则您的问题出错 模型 属性 类型 完全 。所以,我将构造函数更新为 获取IReadOnlyList<Permission>
并成功反序列化:[JsonConstructor] public MenuItem ( string name, string url, IReadOnlyList<Permission> permissions ) { this.Name = name; this.Url = url; this.Permissions = permissions ?? new List<Permission>().AsReadOnly(); }
或者,您可以将
Permissions
属性 更改为List<Permission>
。
这个System.Text.Json
and there is currently an open github issue.
你的 fiddle 的一个工作分支是 demoed here。