WebApi序列化深度和循环引用

时间:2014-02-23 14:41:06

标签: c# asp.net-web-api json.net

我在WebApi Restful服务上返回了一些组合对象(为简单起见):

class Item {
    List<Category> Categories { get; set; }
    object Value { get; set; }
}

class Category {
    List<Item> ItemsInCategory { get; set; }
}

这些值由简单的ApiController提供:

 publicHttpResponseMessage getItems()
 {
     List<Category> categories;
     ...
     return Request.CreateResponse(HttpStatusCode.OK, new { results = items});
 }

问题:假设项目(A)属于类别(A),这将导致循环依赖,这将“卡住”序列化。因此,webapi团队(这是我最后一次使用后端B.T.W)暴露了参考循环处理:(WebApiConfig.cs)

JsonMediaTypeFormatter jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
var jSettings = new JsonSerializerSettings()
     {
        Formatting = Formatting.Indented,
        DateTimeZoneHandling = DateTimeZoneHandling.Utc,
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
     };

jsonFormatter.SerializerSettings = jSettings;

那说它不起作用。 也不是“MaxDepth”属性。
我已经搜索了很多方法,并且找不到实现这一点的内置方法(有很多“黑客”)可以实现JsonConverter(以及[JsonIgnore])的一些变化,这些变化有助于实现这一点。
这是控制响应深度的非常常见请求,不是吗? 微软完全无视这个问题的任何机会,并没有内置的方法来处理这个问题????

1 个答案:

答案 0 :(得分:2)

我认为根本问题是你的API试图在一次通话中做太多。我可能会将其拆分为/api/categories/api/categories/{id}/api/category/{id}/items/api/items/{id}。第一个URL仅返回类别信息,关于类别的第二个详细信息,关于该类别中的项目的第三个信息,以及第四个关于项目的详细信息。您可以在API中展平模型,这样您就不会表示递归数据,而是在获得项目详细信息时包含URL以检索项目所属类别的信息。

例如,/api/items/foo会返回如下内容:

{
    "name" : "foo",
    "value" : "bar",
    "categories" [
       {
           "name" : "Cat A",
           "parent" : {
               "name" : "Top Cat A",
               "location" : "/api/categories/topcata"
           }
           "location" : "/api/categories/cata"
       },
       {
           "name" : "Cat B",
           "parent" : null,
           "location" : "/api/categories/catb"
       }
    ]
}

这会将序列化问题转变为您可以更好地控制的模型映射问题。我认为它还为消费者提供了更清洁,更易于管理的API。