2013-10-29 20 views
5

我有一個類從一個接口繼承,並且我從我的web api返回接口獲取methed,問題是我得到繼承類的值爲json字符串。爲什麼在web api方法中返回接口時,我得到了帶接口值的繼承類的值?

這是接口

public interface IFoo 
    { 
    string A { get ;set ; } 
    string B { get ; set ; } 
    } 

繼承

public class Child : iFoo 
    { 
    string A { get ; set ; } 
    string B { get ; set ; } 
    string C { get ; set ; } 
    string D { get ; set ; } 
    } 

然後我從我的控制器GetMethod

public IFoo GetIFoo() 
     { 
     return ChildInstance ; 
     } 

當前結果給予退貨的IFoo我所有的繼承類和接口的值,但我只想要在json結果中的接口中實現的值。

回答

5

當它擊中Json串行器時,它並不關心該方法的返回類型是什麼。它只知道「我有這個東西,讓我們看看我能用它做什麼」。

如果您希望序列化程序僅包含您的界面所具有的屬性,那麼最好給它一個僅具有界面所具有屬性的對象。您可以考慮使用例如自動映射器將值從ChildInstance複製到這個新對象。

另一種方法更復雜 - 實現您自己的序列化程序,以便Json序列化程序不會有機會參與。

+0

您可以詳細瞭解複雜的方法的位或發送一個鏈接到一些例子。 .. – Mortalus

2

您的方法簽約返回實現IFoo的對象。它可以返回實現IFoo的任何對象,但不能返回Ifoo本身,因爲您無法獲得接口的實例。所以它返回一個Child的實例。

然後JSON序列化程序會給出這個Child的實例並使用反射來計算出它的屬性。它發現A - D並將其序列化。

如果你只想要A - B序列化,那麼你將不得不返回一個只實現了A - B的類的實例。

說了這麼多,如果您使用的是ASP MVC,那麼請查看http://www.creave.dk/post/2009/10/07/Excluding-properties-from-being-serialized-in-ASPNET-MVC-JsonResult.aspx。通過改變你的類定義

public class Child : iFoo 
{ 
    string A { get ; set ; } 
    string B { get ; set ; } 

    [ScriptIgnore] 
    string C { get ; set ; } 
    [ScriptIgnore] 
    string D { get ; set ; } 
} 

那麼你已指示JSON序列只連載A - B

0

如果你不介意返回動態的,你做這樣的事情:

的另一面是,這僅適用開箱如果使用JSON序列化,所以你必須指定「接受:應用程序/ json「來工作。

public class Person 
{ 
    public string Name { get; set; } 
} 

public class User : Person 
{ 
    public string Title { get; set; } 
    public string Email { get; set; } 
} 

public dynamic Get() 
{ 
    var user = new User { Title = "Developer", Email = "[email protected]", Name = "MyName" }; 

    return new { user.Name, user.Email }; 
} 
0

如果控制器方法的返回類型是接口,那麼您還可以應用操作篩選器來僅序列化接口屬性。這樣您就可以始終保持與接口定義的同步,而無需更改實現接口的類的任何屬性。

對於這個你首先必須創建一個自定義InterfaceContractResolver合同分解爲解釋here

public class InterfaceContractResolver : DefaultContractResolver 
    { 
     private readonly Type _interfaceType; 
     public InterfaceContractResolver(Type interfaceType) 
     { 
      _interfaceType = interfaceType; 
     } 

     protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
     { 
      IList<JsonProperty> properties = base.CreateProperties(_interfaceType, memberSerialization); 
      return properties; 
     } 
    } 

然後添加一個動作過濾器(無論是作爲屬性作爲解釋here或全球範圍內,如果你想這是一個默認的行爲),看起來在控制器方法的返回類型,如果它是一個接口使用上面定義的合同解析:

public class InterfaceFilterAttribute : ActionFilterAttribute 
    { 
     public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
     { 
      ObjectContent content = actionExecutedContext.Response.Content as ObjectContent; 
      if (content != null) 
      { 
       Type returnType = actionExecutedContext.ActionContext.ActionDescriptor.ReturnType; 
       if (returnType.IsInterface && content.Formatter is JsonMediaTypeFormatter) 
       { 
        var formatter = new JsonMediaTypeFormatter 
         { 
          SerializerSettings = 
           { 
            ContractResolver = new InterfaceContractResolver(returnType) 
           } 
         }; 
        actionExecutedContext.Response.Content = new ObjectContent(content.ObjectType, content.Value, formatter); 
       } 
      } 
     } 
    }