c# - System.Text.Json - 根据字段属性有条件地使用自定义 JsonConverter
问题描述
我有一个自定义属性[Foo]
实现如下:
public class FooAttribute
: Attribute
{
}
现在我想使用System.Text.Json.JsonSerializer
进入具有该属性的每个字段,以操作如何序列化和反序列化。
例如,如果我有以下课程
class SampleInt
{
[Foo]
public int Number { get; init; }
public int StandardNumber { get; init; }
public string Text { get; init; }
}
当我序列化此类的实例时,我希望自定义int JsonConverter
仅适用于该字段。
public class IntJsonConverter
: JsonConverter<int>
{
public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// do whatever before reading if the text starts with "potato". But this should be triggered only if destination type has the Foo attribute. How?
return reader.GetInt32();
}
public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
{
writer.WriteStringValue("potato" + value.ToString());
}
}
以便序列化
var sample =
new SampleInt
{
Number = 123,
StandardNumber = 456
Text = "bar"
};
像这样
var serializeOptions = new JsonSerializerOptions();
var serializeOptions.Converters.Add(new IntJsonConverter());
var resultJson = JsonSerializer.Serialize(sample, serializeOptions);
以下json的结果
{
"number": "potato123",
"standardNumber": 456,
"text": "bar"
}
而不是在
{
"number": "potato123",
"standardNumber": "potato456",
"text": "bar"
}
以类似的方式,我希望反序列化是有条件的,并且仅在目标字段具有[Foo]
属性时才使用自定义转换器。
使用Newtonsoft,这可以使用合同解析器和CreateProperties
像这样的覆盖方法。
public class SerializationContractResolver
: DefaultContractResolver
{
private readonly ICryptoTransform _encryptor;
private readonly FieldEncryptionDecryption _fieldEncryptionDecryption;
public SerializationContractResolver(
ICryptoTransform encryptor,
FieldEncryptionDecryption fieldEncryptionDecryption)
{
_encryptor = encryptor;
_fieldEncryptionDecryption = fieldEncryptionDecryption;
NamingStrategy = new CamelCaseNamingStrategy();
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
foreach (var jsonProperty in properties)
{
var hasAttribute = HasAttribute(type, jsonProperty);
if (hasAttribute)
{
var serializationJsonConverter = new MyJsonConverter();
jsonProperty.Converter = serializationJsonConverter;
}
}
return properties;
}
private bool HasAttribute(Type type, JsonProperty jsonProperty)
{
var propertyInfo = type.GetProperty(jsonProperty.UnderlyingName);
if (propertyInfo is null)
{
return false;
}
var hasAttribute =
propertyInfo.CustomAttributes
.Any(x => x.AttributeType == typeof(FooAttribute));
var propertyType = propertyInfo.PropertyType;
var isSimpleValue = propertyType.IsValueType || propertyType == typeof(string);
var isSupportedField = isSimpleValue && hasPersonalDataAttribute;
return isSupportedField;
}
}
但我不想使用 Newtonsoft。我想使用新的 dotnetSystem.Text.Json
序列化程序。是否可以以类似的粒度方式使用它?