6

我有一个从接口继承的类,并且我从我的 web api 返回接口获取方法,问题是我将继承类的值作为 json 字符串获取。

这是界面

 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 返回 IFoo

 public IFoo GetIFoo()
        {
        return  ChildInstance ; 
        }

当前结果给了我继承类和接口的所有值,但我只想要在 json 结果中的接口中实现的值。

4

4 回答 4

6

当它遇到 Json 序列化程序时,它并不关心方法的返回类型是什么。它所知道的只是“我有这个对象,让我们看看我能用它做什么”。

如果您希望序列化程序仅包含您的接口所具有的属性,您最好给它一个对象,该对象只具有您的接口所具有的属性。您可能会考虑使用例如 Automapper 将值复制ChildInstance到这个新对象。

另一种方法更复杂 - 实现您自己的序列化程序,这样 Json 序列化程序就没有机会参与其中。

于 2013-10-29T08:23:34.600 回答
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

于 2013-10-29T08:27:28.577 回答
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 = "foo@bar.baz", Name = "MyName" };

    return new { user.Name, user.Email };
}
于 2013-11-01T15:23:25.500 回答
0

如果控制器方法的返回类型是接口,您还可以应用操作过滤器来仅序列化接口属性。这样,您始终与接口定义保持同步,而无需更改实现接口的类的任何属性。

为此,您首先必须创建一个自定义InterfaceContractResolver合同解析器,如下所述

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

然后添加一个操作过滤器(作为此处解释的属性或全局,如果您希望将此作为默认行为)查看控制器方法的返回类型,如果它是一个接口,则使用上面定义的合同解析器:

    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);
                }
            }
        }
    }
于 2016-03-11T20:52:58.050 回答