System.Text.Json:获取自定义转换器中的属性名称
System.Text.Json: Get the property name in a custom converter
使用 JsonSerialize.DeserializeAsync
和自定义转换器反序列化,例如
public class MyStringJsonConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
在这里我会得到 all string
属性,这还可以,但有什么方法可以检查给定的 属性 名称值,例如像这样,在哪里只处理 Body
属性:
class MyMailContent
{
public string Name { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
public class MyStringJsonConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.PropertyName.Equals("Body"))
{
var s = reader.GetString();
//do some process with the string value
return s;
}
return reader.GetString();
}
}
或者是否有其他方法可以挑出给定的 属性?
请注意,我正在寻找使用 System.Text.Json
的解决方案。
System.Text.Json 不会使父 属性 成为名称,或者更一般地说,path to the current value, available inside JsonConverter<T>.Read()
. This information is tracked internally -- it's in ReadStack.JsonPath()
-- but ReadStack
是内部的,从未传递给应用程序代码。
但是,如 Registration sample - [JsonConverter] on a property, you can apply your MyStringJsonConverter
directly to public string Body { get; set; }
by using JsonConverterAttribute
中所述:
class MyMailContent
{
public string Name { get; set; }
public string Subject { get; set; }
[JsonConverter(typeof(MyStringJsonConverter))]
public string Body { get; set; }
}
通过这样做,MyStringJsonConverter.Read()
和 .Write()
将仅针对 MyMailContent.Body
触发。即使你在 JsonSerializerOptions.Converters
, the converter applied to the property will take precedence 中有一些整体 JsonConverter<string>
:
During serialization or deserialization, a converter is chosen for each JSON element in the following order, listed from highest priority to lowest:
[JsonConverter]
applied to a property.
- A converter added to the
Converters
collection.
[JsonConverter]
applied to a custom value type or POCO.
(请注意,这与 Newtonsoft 有部分不同,其中应用于类型的转换器会取代设置中的转换器。)
感谢 Jimi for the ,在他的祝福下,我 post 使用他建议的解决方案进行了 wiki 回答,任何有更多贡献的人,请随时这样做。
在大多数情况下,公认的答案是好的,但如果仍然需要通过 属性 名称处理一个或多个特定属性,这里有一种方法可以做到这一点。
public class MyMailContent
{
public string Name { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
public class MyMailContentJsonConverter : JsonConverter<MyMailContent>
{
public override MyMailContent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
var mailContent = new MyMailContent();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return mailContent;
}
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();
switch (propertyName)
{
case "Name":
mailContent.Name = reader.GetString();
break;
case "Subject":
mailContent.Subject = reader.GetString();
break;
case "Body":
string body = reader.GetString();
//do some process on body here
mailContent.Body = body;
break;
}
}
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, MyMailContent mailcontent, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
private static JsonSerializerOptions _jsonDeserializeOptions = new()
{
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
Converters =
{
new MyMailContentJsonConverter()
}
};
然后像这样使用它
var jsonstring = JsonSerializer.Serialize(new MyMailContent
{
Name = "some name",
Subject = "some subject",
Body = "some body"
});
var MailContent = JsonSerializer.Deserialize<MyMailContent>(jsonstring, _jsonDeserializeOptions);
使用 JsonSerialize.DeserializeAsync
和自定义转换器反序列化,例如
public class MyStringJsonConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
在这里我会得到 all string
属性,这还可以,但有什么方法可以检查给定的 属性 名称值,例如像这样,在哪里只处理 Body
属性:
class MyMailContent
{
public string Name { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
public class MyStringJsonConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.PropertyName.Equals("Body"))
{
var s = reader.GetString();
//do some process with the string value
return s;
}
return reader.GetString();
}
}
或者是否有其他方法可以挑出给定的 属性?
请注意,我正在寻找使用 System.Text.Json
的解决方案。
System.Text.Json 不会使父 属性 成为名称,或者更一般地说,path to the current value, available inside JsonConverter<T>.Read()
. This information is tracked internally -- it's in ReadStack.JsonPath()
-- but ReadStack
是内部的,从未传递给应用程序代码。
但是,如 Registration sample - [JsonConverter] on a property, you can apply your MyStringJsonConverter
directly to public string Body { get; set; }
by using JsonConverterAttribute
中所述:
class MyMailContent
{
public string Name { get; set; }
public string Subject { get; set; }
[JsonConverter(typeof(MyStringJsonConverter))]
public string Body { get; set; }
}
通过这样做,MyStringJsonConverter.Read()
和 .Write()
将仅针对 MyMailContent.Body
触发。即使你在 JsonSerializerOptions.Converters
, the converter applied to the property will take precedence 中有一些整体 JsonConverter<string>
:
During serialization or deserialization, a converter is chosen for each JSON element in the following order, listed from highest priority to lowest:
[JsonConverter]
applied to a property.- A converter added to the
Converters
collection.[JsonConverter]
applied to a custom value type or POCO.
(请注意,这与 Newtonsoft 有部分不同,其中应用于类型的转换器会取代设置中的转换器。)
感谢 Jimi for the
在大多数情况下,公认的答案是好的,但如果仍然需要通过 属性 名称处理一个或多个特定属性,这里有一种方法可以做到这一点。
public class MyMailContent
{
public string Name { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
public class MyMailContentJsonConverter : JsonConverter<MyMailContent>
{
public override MyMailContent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException();
}
var mailContent = new MyMailContent();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return mailContent;
}
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();
switch (propertyName)
{
case "Name":
mailContent.Name = reader.GetString();
break;
case "Subject":
mailContent.Subject = reader.GetString();
break;
case "Body":
string body = reader.GetString();
//do some process on body here
mailContent.Body = body;
break;
}
}
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, MyMailContent mailcontent, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
private static JsonSerializerOptions _jsonDeserializeOptions = new()
{
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
Converters =
{
new MyMailContentJsonConverter()
}
};
然后像这样使用它
var jsonstring = JsonSerializer.Serialize(new MyMailContent
{
Name = "some name",
Subject = "some subject",
Body = "some body"
});
var MailContent = JsonSerializer.Deserialize<MyMailContent>(jsonstring, _jsonDeserializeOptions);