Я пытаюсь создать уровень абстракции для десериализации Json.NET с использованием интерфейсов.Чтобы добиться этого, я использую пользовательский JsonConverter
, который прекрасно работает, пока не будут представлены интерфейсы.Выдается следующее исключение:
Необработанное исключение: Newtonsoft.Json.JsonSerializationException: Ошибка при установке значения «Items» в «BatchList».---> System.InvalidCastException: невозможно преобразовать объект типа 'System.Collections.Generic.List1 [BatchItems]' в тип 'System.Collections.Generic.List`1 [IBatchItems]
Это настройка для воспроизведения в консольном приложении:
class Program
{
static void Main(string[] args)
{
var jsonBatch = @"{'items': [{'Id': 'name1','info': {'age': '20'}},{'Id': 'name2','info': {'age': '21'}}]}";
DeserializeAndPost(jsonBatch);
}
public static void DeserializeAndPost(string json)
{
IBatchList req;
req = JsonConvert.DeserializeObject<BatchList>(json);
Post(req);
}
public static void Post(IBatchList batchList)
{
Console.WriteLine(batchList.Items.FirstOrDefault().Id);
}
}
public interface IBatchList
{
List<IBatchItems> Items { get; set; }
}
public interface IBatchItems
{
string Id { get; set; }
JObject Info { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class BatchList : IBatchList
{
[JsonProperty(PropertyName = "Items", Required = Required.Always)]
[JsonConverter(typeof(SingleOrArrayConverter<BatchItems>))]
public List<IBatchItems> Items { get; set; }
}
[JsonObject]
public class BatchItems : IBatchItems
{
[JsonProperty(PropertyName = "Id", Required = Required.Always)]
public string Id { get; set; }
[JsonProperty(PropertyName = "Info", Required = Required.Always)]
public JObject Info { get; set; }
}
// JsonConverter
public class SingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
List<T> list = (List<T>)value;
if (list.Count == 1)
{
value = list[0];
}
serializer.Serialize(writer, value);
}
public override bool CanWrite
{
get { return true; }
}
}
Я ожидаю, что выходные данные будут десериализованы в формате JSON, поскольку я предоставляю тип интерфейса, который будет использоваться для десериализации:
[JsonConverter(typeof(SingleOrArrayConverter<BatchItems>))]
использоваться.Вместо этого выдается unhandled cast exception
.
Обратите внимание, что если я использую вместо SingleOrArrayConverter<IBatchItems>
, я получу исключение
Newtonsoft.Json.JsonSerializationException: Could not create an instance of type
, поскольку [JsonConverter(typeof(SingleOrArrayConverter<BatchItems>))]
предназначен для предоставления конкретного типадля следующего интерфейса: public List<IBatchItems> Items { get; set; }
.