实现 IEnumerable <T>类型的 MVC 控制器 Json 序列化



我有以下代码表示分页查询的结果。

public class Page<T> : IEnumerable<T>
{
    public IEnumerable<T> Source { get; }
    public int PageNumber { get; }
    public int PageSize { get; }
    public int TotalCount { get; }
    public int TotalPages => TotalCount / PageSize + (TotalCount % PageSize > 0 ? 1 : 0);
    public Page(
        IEnumerable<T> source,
        int pageNumber,
        int pageSize,
        int totalCount)
    {
        Source = source;
        PageNumber = pageNumber;
        PageSize = pageSize;
        TotalCount = totalCount;
    }
    public IEnumerator<T> GetEnumerator()
    {
        return Source.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

下面是一个 MVC 控制器方法,它通过 MVC Json 序列化程序(不是 WebAPI 序列化程序(返回一页结果。

    [HttpGet, Route("mergeable")]
    public async Task<ActionResult> Mergeable([FromUri] Mergeable.Query query)
    {
        Page<Mergeable.Model> result = await mediator.Send(query);
        return Json(result, JsonRequestBehavior.AllowGet);
    }

调用时,响应 Json 是 T 数组。所有分页元属性(总计数、页码、页面大小(都不会序列化。

默认的 MVC Json 序列化程序(无论是什么(是否忽略 IEnumerable 实例上的其他属性?如何覆盖此行为?

ASP.NET Web API和 ASP.NET Core MVC(也运行在完整框架上(使用 Json.NET。 Json.NET 还将从实现IEnumerable的对象生成一个数组。

此代码将生成[1,2,3]

var page=new Page<int>(new int[]{1,2,3},1,10,100);
var text=Newtonsoft.Json.JsonConvert.SerializeObject(page);

Json.NET 允许您指定如何通过 JsonObject 或 JsonArray 等属性序列化对象。如果将 JsonObject 属性添加到 Page 类,它将被序列化为:

{"Source":[1,2,3],"PageNumber":1,"PageSize":10,"TotalCount":100,"TotalPages":10}

ASP.NET MVC仍然使用相当旧的JavaScriptSerializer,其描述是:

Json.NET 应使用序列化和反序列化。为启用 AJAX 的应用程序提供序列化和反序列化功能。

您可以将 MVC 配置为使用 ASP.NET Json.NET,如本 SO 问题所示。如果您不想这样做,可以使用 Json.NET 序列化为字符串并返回具有 JSON 内容类型的字符串,例如:

 return Content(JsonConvert.SerializeObject(page), "application/json");

这是一个 Json 格式限制,json 格式不支持具有附加属性的 comlex 数组。

实现IEnumerable对象的 json 序列化行为是忽略其他属性,仅从 GetEnumerator() 进行序列化。

可以使用 Source 属性获取元素并避免Page<T> : IEnumerable<T>实现。

最新更新