我正在为Web API进行复杂的数据传输。它假设发送具有嵌套多态属性的类集合的结构。默认情况下,默认的JSON转换器无法识别多态结构。 我试图使用完整的命名空间解析。不幸的是,在我的场景中,它没有工作,因为我在客户端服务器端有不同的框架(完整框架和.net核心),它没有正确解析它的命名空间和程序集。 (是的,我尝试了程序集和命名空间的映射,并意识到它将是无法支持的混乱)
我认为自定义转换器应该能够正常工作,遗憾的是我对如何正确编写它并不了解。
我有一个带有一些属性的主上下文和一个容器集合。 每个Container都具有多态属性,序列化应该使用包含类名的额外参数'type'来解析
我修复了此示例中的所有问题,代码完全正常工作
public class MyConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteStartArray();
var t = value as List<Container>;
foreach (var e in t)
{
var container = new JObject();
var fi = e.PropertyA;
JObject o = JObject.FromObject(fi);
o.AddFirst(new JProperty("type", new JValue(fi.GetType().Name)));
container.Add(new JProperty("PropertyA", o));
var res = e.PropertyB;
o = JObject.FromObject(res);
o.AddFirst(new JProperty("type", new JValue(res.GetType().Name)));
container.Add(new JProperty("PropertyB", o));
container.WriteTo(writer);
}
writer.WriteEndArray();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return string.Empty;
}
else if (reader.TokenType == JsonToken.String)
{
return serializer.Deserialize(reader, objectType);
}
else
{
JArray array = JArray.Load(reader);
List<Container> collection = new List<Container>();
foreach (var item in array.Children())
{
JToken propATkn = item.First;
JToken propBTkn = propATkn.Next;
var strType = ((JProperty)(propATkn.OfType<JObject>()).First().First).Value.ToString();
Type type = Type.GetType(strType);
BaseClassA propA = propATkn.OfType<JObject>().FirstOrDefault().ToObject(type) as BaseClassA;
strType = ((JProperty)(propBTkn.OfType<JObject>()).First().First).Value.ToString();
type = Type.GetType(strType);
BaseClassB propB = propBTkn.OfType<JObject>().FirstOrDefault().ToObject(type) as BaseClassB;
collection.Add(new Container { PropertyA = propA, PropertyB = propB});
}
return collection;
}
}
public override bool CanWrite
{
get { return true; }
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
public class Context
{
[JsonConverter(typeof(MyConverter))]
public IList<Container> sources { get; set; } = new List<Container>();
public int Value { get; set; }
public string Key { get; set; }
}
public class Container
{
public BaseClassA PropertyA { get; set; }
public BaseClassB PropertyB { get; set; }
}
public class BaseClassB
{
public int B;
}
public class ClassBA : BaseClassB
{
public int BA;
}
public class ClassBB : BaseClassB
{
public int BB;
}
public class BaseClassA
{
public int A;
}
public class ClassAA : BaseClassA
{
public int AA;
}
public class ClassAB : BaseClassA
{
public int AB;
}