Использование атрибутов свойств, чтобы определить, какой JsonConverter использовать - PullRequest
0 голосов
/ 31 января 2019

Мне нужно указать JsonConverter для свойств, которые украшены определенным атрибутом, в этом случае [DataType(DataType.PostalCode)].

У меня уже есть пользовательский JsonConverter, для которого я установилCanConvert метод следующим образом:

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

Как я могу убедиться, что вместо этого используется PostcodeJsonConverter, когда API встречает свойство 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 голосов
/ 31 января 2019

Вы можете создать пользовательский 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

0 голосов
/ 31 января 2019

Вы можете добавить конвертеры в настройки JsonSerializer.Таким образом, вместо того, чтобы украшать все, вы можете также добавить свой PostcodeJsonConverter туда (в зависимости от того, как часто он используется, хотя декоратор может быть лучше):

Для значений по умолчанию ядра aspnet:

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

Для JsonConvert:

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