我有一个User
具有属性的类 Roles
类型 ISet<Role>
,其中Role
是 enum
类型。在 JSON 中,我得到该属性的一个数组(例如 "Roles":["Admin","User"]
)。我如何编写一个自定义转换器来将此数组转换为 ISet
收藏?
我尝试编写这个类:
class CustomStringToRoleConverter : JsonConverter<ISet<User.Role>> {
public override ISet<User.Role> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
return null;
}
public override void Write(Utf8JsonWriter writer, ISet<User.Role> roles, JsonSerializerOptions options) {
StringBuilder builder = new StringBuilder();
builder.Append(string.Join(",", roles.Select(role => role.ToString()).ToArray()));
writer.WriteStartArray();
writer.WriteStringValue(builder.ToString());
writer.WriteEndArray();
}
}
但我不知道在 Read
做什么方法。如何从 Utf8JsonReader
获取数组?有一个GetString
方法,但当我调用它时它抛出异常:
InvalidOperationException: Cannot get the value of a token type 'StartArray' as a string.
我正在使用System.Text
和System.Text.Json
.
最佳答案
JSON "Roles":["Admin","User"]
property 是字符串值的数组,而不是包含逗号分隔值的单个字符串值。因此,编写自定义转换器的最简单方法如下:
class CustomStringToRoleConverter : JsonConverter<ISet<User.Role>> {
public override ISet<User.Role> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
JsonSerializer.Deserialize<List<string>>(ref reader, options)
?.Select(s => Enum.Parse<User.Role>(s))
?.ToHashSet(); // Or use a SortedSet if you prefer
public override void Write(Utf8JsonWriter writer, ISet<User.Role> roles, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, roles.Select(r => r.ToString()), options);
}
转换器只是序列化和反序列化字符串集合,然后将项目解析或格式化为 Role
枚举作为后处理或预处理步骤。 (为了进行比较,您现有的 Write()
方法将生成 "Roles": ["Admin,User"]
,它与问题开头段落中显示的 JSON 不匹配。)
示例 fiddle #1 here .
如果您非常关心性能并且更喜欢一种不反序列化为中间的更“手动”的方法 List<string>
,你可以这样做:
class CustomStringToRoleConverter : JsonConverter<ISet<User.Role>> {
public override ISet<User.Role> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
return null; // Or throw an exception if you don't want to allow null
else if (reader.TokenType != JsonTokenType.StartArray)
throw new JsonException();
var set = new HashSet<User.Role>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
return set;
else if (reader.TokenType == JsonTokenType.String)
set.Add(Enum.Parse<User.Role>(reader.GetString()));
else
{
//reader.Skip();
throw new JsonException(); // Unexpected token;
}
}
throw new JsonException(); // Truncated file;
}
public override void Write(Utf8JsonWriter writer, ISet<User.Role> roles, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (var value in roles)
writer.WriteStringValue(value.ToString());
writer.WriteEndArray();
}
}
示例 fiddle #2 here .
或者,您可以简单地添加 JsonStringEnumConverter
至 JsonSerializerOptions.Converters
将所有枚举序列化为字符串。
关于c# - 如何使用System.Text.Json将json数组转换为集合;,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66750433/