使用属性属性定义要使用的JsonConverter

时间:2019-01-31 13:24:33

标签: c# json.net asp.net-core-webapi

我需要为装饰有特定属性的属性指定JsonConverter,在这种情况下为[DataType(DataType.PostalCode)]

我已经有一个自定义JsonConverter,我已经为其设置了CanConvert方法,如下所示:

public override bool CanConvert(Type objectType) => objectType == typeof(string);

当API遇到PostcodeJsonConverter属性时,如何确保使用PostalCode代替?

[DataType(DataType.PostalCode)]
public string Postcode { get; set; }

我尝试了以下操作,但是我怀疑DataType属性目前不可用。

public override bool CanConvert(Type objectType) => 
    objectType == typeof(string) && 
    objectType.GetCustomAttributes(true)
              .OfType<DataTypeAttribute>()
              .Any(dta => dta.DataType == DataType.PostalCode);

我是否需要按如下方式装饰模型?

[DataType(DataType.PostalCode)]
[JsonConverter(typeof(PostcodeJsonConverter))]
public string Postcode { get; set; }

2 个答案:

答案 0 :(得分:2)

您可以创建一个自定义ContractResolver,以在每个属性上查找您的DataType属性,并将这些值映射到适当的转换器。这是您需要的代码:

public class DataTypeResolver : DefaultContractResolver
{
    private Dictionary<DataType, JsonConverter> ConvertersByDataType { get; set; }

    public DataTypeResolver()
    {
        // Adjust this list to match your actual data types and converters
        ConvertersByDataType = new Dictionary<DataType, JsonConverter>
        {
            { DataType.PostalCode, new PostalCodeConverter() },
            { DataType.PhoneNumber, new PhoneNumberConverter() },
        };
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        var att = prop.AttributeProvider.GetAttributes(true).OfType<DataTypeAttribute>().FirstOrDefault();
        if (att != null)
        {
            JsonConverter converter;
            if (ConvertersByDataType.TryGetValue(att.DataType, out converter))
            {
                prop.Converter = converter;
            }
        }
        return prop;
    }
}

然后通过设置将解析器传递到SerializeObject和/或DeserializeObject

var settings = new JsonSerializerSettings
{
    ContractResolver = new DataTypeResolver()
};
string json = JsonConvert.SerializeObject(yourObject, settings);

这是一个有效的演示:https://dotnetfiddle.net/k1kWv5

答案 1 :(得分:0)

您可以将Converters添加到JsonSerializerSettings。因此,除了装饰所有内容之外,您还可以在其中添加PostcodeJsonConverter(取决于使用频率,装饰器可能会更好):

对于aspnet核心默认设置:

services.AddMvc().AddJsonOptions(o => o.SerializerSettings.Converters.Add(new PostcodeJsonConverter()))

对于JsonConvert:

JsonConvert.SerializeObject(obj, new JsonSerializerSettings
{
    Converters = { new PostcodeJsonConverter() }
});