繁体   English   中英

自参考导航属性和json序列化

[英]Self reference navigation property and json serialization

我有一个公开用户的Web API。

每个用户都有一个管理员,该管理员也是一个用户。

在我的EDMX中,我在“用户”实体上有一个自已的1 .. *导航属性,它是从管理员到用户的导航的“合作者”,而从用户到他的经理的导航的是“经理”。

我的JSON API使用NewtonJSON序列化实体。

为了自定义API调用的JSON结果,我在查询字符串中实现了关键字“ fields”。 使用“字段”可以获取用户的部分JSON表示形式。

呼叫看起来像这样:/ api / users?fields = id,name,department,picture

您会从完整的C#用户对象中获得仅具有ID,名称,部门和图片属性的JSON。

我已经使用IContractResolver的自定义实现来实现此目的。

问题在于,NewtonJSON合同解析器是“按类型”而不是“按对象”工作的,这意味着您可以告诉序列化程序将声明类型的成员而不是另一个声明类型序列化,但是您不能告诉它(如据我所知,这就是为什么我在这里要求)序列化此类型的此对象的成员,而不是序列化同一类型的另一个对象的相同成员。

就是说,我的问题是当我要求:/ api / users?fields = id,name,manager

我在每个用户对象上通过管理器成员的递归序列化得到响应,如下所示:

[{
    id: 123,
    name: "Foo",
    manager:
    {
        id: 124,
        name: "Foo",
        manager:
        {
            id: 125,
            name: "Foo",
            manager:
            {
            ...
            }
        }
    }
},
{
    id: 124,
    name: "Foo",
    manager:
    {
        id: 125,
        name: "Foo",
        manager:
        {
        ...
        }
    }
},
{
    id: 125,
    name: "Foo",
    manager:
    {
    ...
    }
}]

我还实现了要求部分子实体响应的功能,如下所示:

/api/users?fields=id,name,manager.id

但是由于主对象(这里是用户)和子对象(管理器)都属于同一类型,因此无法使用。

是否有人已经使用NewtonJSON来实现部分响应Web API? 您如何管理嵌入式自我类型实体?

感谢您的建议。

您可以编写一个可以理解fields参数并转换响应的动作过滤器。 我有一个将响应对象转换成Dictionary的示例实现。 关键字是客户端询问的字段,值是响应中返回的对象的字段值。 该实现只是一个示例,还远远不能完成:)

public class FieldFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var fieldsParameter = actionExecutedContext.Request.GetQueryNameValuePairs().Where(kvp => kvp.Key == "fields");
        if (fieldsParameter.Count() == 1)
        {
            object response;
            object newResponse;

            if (actionExecutedContext.Response.TryGetContentValue(out response))
            {
                string[] fields = fieldsParameter.First().Value.Split(',');

                IEnumerable<object> collection = response as IEnumerable<object>;
                if (collection != null)
                {
                    newResponse = collection.Select(o => SelectFields(fields, o));
                }
                else
                {
                    newResponse = SelectFields(fields, response);
                }

                actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.OK, newResponse);
            }
        }
    }

    private static Dictionary<string, object> SelectFields(string[] fields, object value)
    {
        Dictionary<string, object> result = new Dictionary<string, object>();

        foreach (string field in fields)
        {
            result.Add(field, GetValue(field, value));
        }

        return result;
    }

    private static object GetValue(string indexer, object value)
    {
        string[] indexers = indexer.Split('.');

        foreach (string property in indexers)
        {
            PropertyInfo propertyInfo = value.GetType().GetProperty(property);
            if (propertyInfo == null)
            {
                throw new Exception(String.Format("property '{0}' not found on type '{1}'", property, value.GetType()));
            }

            value = propertyInfo.GetValue(value);

            if (value == null)
            {
                return null;
            }
        }

        return value;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM