2016-09-30 119 views
0

我們正在使用.Net 4.6構建Web Api應用程序我們正在嘗試JsonConvert.DeserializeObject一個複雜對象。該對象具有複雜對象的列表,並且該對象是一個接口。 因此,我們有一個Task類具有TaskDetails列表和類有IBehaviorJson使用Interface作爲屬性反序列化一個複雜對象

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" 
    } 
} 

我收到以下錯誤:

"The request is invalid.","modelState":{"task.taskDetails[0].behavior.pSet":["Could not create an instance of type Bl.Models.EPA.IBehavior. Type is an interface or abstract class and cannot be instantiated. Path '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; } 
+0

的可能的複製[鑄造界面在JSON.NET反序列化(http://stackoverflow.com/questions/5780888/casting-interfaces-for-deserialization-in-json-淨) – BWA

回答

0

事實證明,我可以將TaskDetail中的屬性從IBehavior更改爲動態,並且可以工作。然後,當我需要使用具體類型時,我有一個可以返回具體類型的工廠(即torqueTool)。在這一點上我可以做

JsonConvert.DeserializeObject<TorqueTool>(taskDetail.Behavior.ToString()); 
0

我相信Deserializer不知道該怎麼映射接口,所以提供一些Deserializer提示可以做到這一點。

public class TaskDetail 
{ 
    TaskDetails(PartPick partPick) 
    { 
     Behavior = partPick; 
    } 

    TaskDetails(TorqueTool torqueTool) 
    { 
     Behavior = torqueTool; 
    } 

    public int Id { get; set; } 
    public IBehavior Behavior { get; set; } 
} 
0

也許this answer將適合你。基本上他們提出的是傳遞實現這個接口的類的實例。

public class TaskDetail 
{ 
    public TaskDetail(TorqueTool behavior){ 
     Behavior = behavior; 
    } 
    public int Id { get; set; } 
    public IBehavior Behavior { get; set; } 
} 
0

如果您正在使用的DataContractSerializer,您應該使用"KnownTypes"屬性來定義應用程序,您所期待實現該接口的類型。

如果您正在使用XML序列化程序,則需要使用this問題中所見的每種類型的「XmlInclude」屬性對其進行標記。