我们正在使用。net 4.6构建一个Web Api应用程序我们正在尝试json转换。反序列化对象:复杂对象。该对象有一个复杂对象列表,该对象中有一个接口。我们有一个任务类有一个TaskDetails列表这个类有一个IBehavior
属性public class Task
{
public int Id { get; set; }
public int TaskTypeId { get; set; } //TYPE
public List<TaskDetail> TaskDetails { get; set; }
}
public class TaskDetail
{
public int Id { get; set; }
public IBehavior Behavior { get; set; }
}
IBehavior是一个空接口…
public interface IBehavior
{
}
和具体行为是…
public class PartPick : IBehavior
{
public bool AllowMultiplePicks { get; set; }
public bool RunLightsOnly { get; set; }
public bool StandardLightMode { get; set; }
}
或
public class TorqueTool : IBehavior
{
public short PSet { get; set; }
public short RundownsRequired { get; set; }
public int MultiSpindleMask { get; set; }
}
JSon有效负载是:
{
"id": 10000,
"name": "Attach Spoiler",
"taskTypeId": 1,
"behavior": {
"pSet": 1,
"rundownsRequired": 1,
"multiSpindleMask": 4,
"multiSpindleMaskString": "0010000000000000"
}
}
我得到以下错误:
" request is invalid.","modelState":{"task.taskDetails[0].behavior. "pSet":["无法创建Bl.Models.EPA.IBehavior类型的实例。类型是接口或抽象类,不能实例化。路径的taskDetails [0] .behavior.pSet '
我尝试创建一个JsonBodyModelbinder: IModelBinder其中反序列化的方法为:
private static T DeserializeObjectFromJson(string json)
{
var binder = new TypeNameSerializationBinder("");
var obj = JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Binder = binder
});
return obj;
}
,它被连接在httpConfiguration中:
config.Services.Insert(typeof(ModelBinderProvider), 0,
new SimpleModelBinderProvider(typeof(IBehavior), new JsonBodyModelBinder<IBehavior>()));
我也试过把下面的属性放在TaskDetail的IBehavior属性上。
[JsonConverter(typeof(JsonBodyModelBinder<IBehavior>))]
public IBehavior Behavior { get; set; }
也许这个答案适合你。基本上,他们提出的是传递实现这个IBehavior
接口的类的实例。
public class TaskDetail
{
public TaskDetail(TorqueTool behavior){
Behavior = behavior;
}
public int Id { get; set; }
public IBehavior Behavior { get; set; }
}
如果你正在使用DataContractSerializer,你应该使用"KnownTypes"属性来定义你希望实现该接口的类型。
如果您正在使用XML序列化器,则需要为每个类型标记"XmlInclude"属性,如本问题所示。
事实证明,我可以将TaskDetail中的属性从IBehavior更改为dynamic,并且它有效。然后,当我需要使用混凝土类型时,我有一个可以返回混凝土类型的工厂(即torqueTool)。此时我可以输入
JsonConvert.DeserializeObject<TorqueTool>(taskDetail.Behavior.ToString());
我相信反序列化器不知道将接口映射到什么,所以提供一些反序列化器的提示将会起到作用。
public class TaskDetail
{
TaskDetails(PartPick partPick)
{
Behavior = partPick;
}
TaskDetails(TorqueTool torqueTool)
{
Behavior = torqueTool;
}
public int Id { get; set; }
public IBehavior Behavior { get; set; }
}