我不确定您的 MyJsonConverter 实际上做了什么,但作为一个基本示例,您只需要提供 JsonSerializerSettings 并将 TypeNameHandling 属性设置为 TypeNameHandling.All
这个简单的例子有效。
public interface IControl { }
public class Form
{
public IList<IControl> Controls { get; set; }
}
public class ControlA : IControl { }
public class ControlB : IControl { }
static void Main(string[] args)
{
var form = new Form();
form.Controls = new List<IControl>();
form.Controls.Add(new ControlA());
form.Controls.Add(new ControlB());
var json = JsonConvert.SerializeObject(form, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
var obj = JsonConvert.DeserializeObject<Form>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
}
编辑
在澄清没有使用类型处理因此没有$type 属性之后,我们必须获得更多创意并阅读原始jSON。并以特别的方式构造对象。这是客户序列化程序的示例。
internal class MyJsonConverter : CustomCreationConverter<IControl>
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var controlType = jObject["CustomProperty"]?.Value<string>();
IControl control = null;
if (!string.IsNullOrWhiteSpace(controlType))
{
switch (controlType.ToLowerInvariant())
{
case "controla":
control = Activator.CreateInstance(typeof(ControlA)) as IControl;
break;
case "controlb":
control = Activator.CreateInstance(typeof(ControlB)) as IControl;
break;
}
}
if (controlType == null)
throw new SerializationException($"Unable to deserialize property. {controlType}");
serializer.Populate(jObject.CreateReader(), control);
return control;
}
public override IControl Create(Type objectType)
{
return null;
}
}
基本上,由于我们依赖IControl 接口中的属性(已在问题中省略),我们将手动解析 json 并获取对属性 CustomProperty 的引用
如果此属性存在一个有效的字符串值(或者您可以使用任何其他您希望的值),我们将手动创建我们的IControl。
最后处理反序列化的部分是最后一行serializer.Populate()
完整的测试用例:
internal class MyJsonConverter : CustomCreationConverter<IControl>
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var controlType = jObject["CustomProperty"]?.Value<string>();
IControl control = null;
if (!string.IsNullOrWhiteSpace(controlType))
{
switch (controlType.ToLowerInvariant())
{
case "controla":
control = Activator.CreateInstance(typeof(ControlA)) as IControl;
break;
case "controlb":
control = Activator.CreateInstance(typeof(ControlB)) as IControl;
break;
}
}
if (controlType == null)
throw new SerializationException($"Unable to deserialize property. {controlType}");
serializer.Populate(jObject.CreateReader(), control);
return control;
}
public override IControl Create(Type objectType)
{
return null;
}
}
[JsonConverter(typeof(MyJsonConverter))]
public interface IControl
{
string CustomProperty { get; set; }
}
public class Form
{
public IList<IControl> Controls { get; set; }
}
public class ControlA : IControl
{
public string CustomProperty { get; set; } = "ControlA";
}
public class ControlB : IControl
{
public string CustomProperty { get; set; } = "ControlB";
}
static void Main(string[] args)
{
var form = new Form();
form.Controls = new List<IControl>();
form.Controls.Add(new ControlA());
form.Controls.Add(new ControlB());
var json = JsonConvert.SerializeObject(form);
var obj = JsonConvert.DeserializeObject<Form>(json);
}