我的問題是,我需要反序列化JSON到一個類型,該類型又包含接口類型對象,因此需要指示Json.NET如何轉換該接口類型,但我不直接控制Newtonsoft.Json.Deserializer
。反序列化由框架代碼間接處理,即由HttpContent.ReadAsAsync<T>處理。如何指示Json.NET將接口類型轉換爲具體類型而無需訪問序列化程序?
如何指定從接口類型到具體類型的轉換,但無法直接向JsonSerializer.Converters
添加轉換器?如果我在接口定義上使用[JsonConverter]
屬性,轉換器也會被調用以實現接口(即,我要轉換的具體類型)。
在下面的代碼示出了嘗試將反序列化相同的JSON首先將Parent2
類,然後將Parent1
類,指示Json.NET經由JsonConverterAttribute
的IChild1
接口類型轉換爲Child1
具體類型C#控制檯程序。由於我將ChildConverter
直接添加到serializer.Converters
,而反序列化到Parent1
會導致堆棧溢出異常,因爲即使對Child1
類型也調用ChildConverter.Deserialize
,因此將其反序列化爲Parent2
。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;
namespace TestConsole
{
[JsonConverter(typeof(ChildConverter))]
interface IChild1
{
string Name { get; set; }
}
class Child1 : IChild1
{
public string Name { get; set; }
}
class Parent1
{
public IEnumerable<IChild1> Children { get; set; }
}
interface IChild2
{
string Name { get; set; }
}
class Child2 : IChild2
{
public string Name { get; set; }
}
class Parent2
{
public IEnumerable<IChild2> Children { get; set; }
}
class ChildConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IChild1) || objectType == typeof(IChild2);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (objectType == typeof(IChild1))
return serializer.Deserialize<Child1>(reader);
return serializer.Deserialize<Child2>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
var json = "{'Children': [{'Name': 'Child1'}, {'Name': 'Child2'}]}";
var serializer = new JsonSerializer();
serializer.Converters.Add(new ChildConverter());
var obj = serializer.Deserialize(new StringReader(json), typeof(Parent2));
serializer = new JsonSerializer();
obj = serializer.Deserialize(new StringReader(json), typeof(Parent1));
}
}
}