Конвертер json с одним значением в коллекцию с общей инициализацией - PullRequest
0 голосов
/ 19 сентября 2018

Некоторое время назад мне понадобился собственный универсальный json-конвертер, который автоматически преобразовывал бы объект в коллекцию, если это необходимо.Мое решение было:

public class SingleValueCollectionConverter<T> : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return reader.TokenType == JsonToken.StartArray ? serializer.Deserialize(reader, objectType) : new List<T> { (T)serializer.Deserialize(reader, typeof(T)) };
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

Это работало нормально, пока у меня не возникла ситуация, когда мне нужно было использовать его для свойства с универсальным типом.У меня есть ошибка при использовании этого как это:

[JsonConverter(typeof(SingleValueCollectionConverter<TData>))]
public List<TData> Data { get; set; }

Оказалось, что общие параметры не могут появляться в объявлениях атрибутов.Я нашел этот запрос на получение доступа к newtonsoftJsonConverter - https://github.com/JamesNK/Newtonsoft.Json/issues/1332, где было предложено решение, но оно не было одобрено автором.Итак, я создал неуниверсальный конвертер, который работает как универсальный с помощью рефлексии:

   public class SingleValueCollectionConverter : JsonConverter
   {
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      {
         throw new NotImplementedException();
      }

      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
         foreach (var prop in objectType.GetProperties())
         {
             var type = prop.PropertyType;

             if (!type.IsClass)
                 continue;

             var destination = Activator.CreateInstance(objectType);
             var result = reader.TokenType == JsonToken.StartArray 
                 ? serializer.Deserialize(reader, objectType) 
                 : new List<object> { serializer.Deserialize(reader, type) };

             return Mapper.Map(result, destination, result.GetType(), destination.GetType());
            }

            return null;
        }

        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    }

Используя вот так:

 [JsonConverter(typeof(SingleValueCollectionConverter))]
 public List<TData> Data { get; set; }

Работает нормально, но, может быть, у кого-то лучшерешение.Буду признателен за любые предложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...