You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

返回JObject时出现Stack overflow问题排查求助

Azure函数返回JObject触发栈溢出(仅Accept头为application/vnd.api+json时)

问题复现

以下Azure HTTP触发器代码,当请求头Accept: application/vnd.api+json时会触发栈溢出,终端反复输出序列化相关的循环调用栈;移除该头则正常运行:

[FunctionName("HttpTrigger1")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    var array = JObject.FromObject(new {dd=1,ddd=2});
    var errorresult = new ObjectResult(array);
    return errorresult;
}

循环调用栈片段:

CollectionDataContractAttribute ByRef)
   at System.Runtime.Serialization.DataContract.GetNonDCTypeStableName(System.Type)
   at System.Runtime.Serialization.DataContract.GetStableName(System.Type, Boolean ByRef)
   at System.Runtime.Serialization.DataContract.GetCollectionStableName(System.Type, System.Type, System.Runtime.Serialization.CollectionDataContractAttribute ByRef)
   ...(循环重复)

原因分析

当请求指定Accept: application/vnd.api+json时,ASP.NET Core默认会选用DataContractSerializer处理响应序列化,但Newtonsoft.Json的JObject类型内部结构与DataContractSerializer的处理逻辑不兼容,导致序列化过程中出现无限递归调用,最终引发栈溢出。而默认的application/json头会使用Newtonsoft.Json或System.Text.Json格式化器,能正确处理JObject。

解决方案

方案1:改用JsonResult替代ObjectResult

直接使用JsonResult指定序列化逻辑,避免触发DataContractSerializer:

[FunctionName("HttpTrigger1")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    var array = JObject.FromObject(new {dd=1,ddd=2});
    // 直接返回JsonResult,默认用Newtonsoft.Json处理
    return new JsonResult(array);
}

如果需要指定application/vnd.api+json作为响应ContentType:

return new JsonResult(array)
{
    ContentType = "application/vnd.api+json"
};

方案2:配置格式化器,让application/vnd.api+json使用Newtonsoft.Json

在Azure函数的配置类(隔离进程模式用Program.cs,In-Process模式用Startup.cs)中,为application/vnd.api+json添加NewtonsoftJsonOutputFormatter:

// 隔离进程模式Program.cs示例
var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddMvcCore(options =>
        {
            var mediaType = MediaTypeHeaderValue.Parse("application/vnd.api+json");
            var newtonsoftFormatter = new NewtonsoftJsonOutputFormatter(
                new JsonSerializerSettings(),
                ArrayPool<char>.Shared,
                options);
            newtonsoftFormatter.SupportedMediaTypes.Add(mediaType);
            options.OutputFormatters.Insert(0, newtonsoftFormatter);
        });
    })
    .Build();

host.Run();

方案3:避免直接返回JObject

将JObject转换为匿名对象或强类型POCO,让DataContractSerializer可以正确处理:

[FunctionName("HttpTrigger1")]
public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log)
{
    // 直接用匿名对象,无需转JObject
    var data = new {dd=1,ddd=2};
    return new ObjectResult(data);
}

内容的提问来源于stack exchange,提问作者tulipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:25:19