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

ASP.NET Core 6 Web API混合返回JSON的问题及修复方案咨询

ASP.NET Core 6 Web API混合返回JSON字符串与C#对象的问题修复方案

问题描述

开发ASP.NET Core 6 Web API控制器时,尝试在接口中同时返回JSON字符串与普通C#对象,遇到两个问题:

  1. JObject类型字段值丢失;
  2. 字符串类型的JSON数据被自动编码,无法直接作为JSON结构使用。

复现代码

[HttpGet("GetMixedJson")]
public IActionResult GetMixedJson()
{
    string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    string json = JsonConvert.SerializeObject(Summaries, Formatting.Indented);

    JObject jsonObject = new JObject();
    jsonObject["thisFiledValueWillBeMissing"] = "JObject won't serialize :(";

    var resultObject = new
    {
        PlainCSharpFiled = "plain c# fields showing fine",
        jsonObject = jsonObject,
        TunneledJsonString = json
    };

    return new JsonResult(resultObject);
}

错误返回结果

{
  "plainCSharpFiled": "plain c# fields showing fine",
  "jsonObject": {
    "thisFiledValueWillBeMissing": []
  },
  "tunneledJsonString": "[\n  \"Freezing\",\n  \"Bracing\",\n  \"Chilly\",\n  \"Cool\",\n  \"Mild\",\n  \"Warm\",\n  \"Balmy\",\n  \"Hot\",\n  \"Sweltering\",\n  \"Scorching\"\n]"
}

问题原因

  • JObject是Newtonsoft.Json的类型,而ASP.NET Core默认使用System.Text.Json序列化,两者兼容性不足,导致JObject字段被错误解析为空数组;
  • 直接返回预序列化的JSON字符串时,System.Text.Json会将其视为普通字符串进行转义编码,无法保留原生JSON结构。

修复方案

方案一:统一使用Newtonsoft.Json序列化(推荐,低内存开销)

替换ASP.NET Core默认序列化器为Newtonsoft.Json,完美兼容JObject,同时避免重复序列化操作,降低内存占用。

  1. 安装NuGet包:
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
  1. 在Program.cs中配置服务:
builder.Services.AddControllers().AddNewtonsoftJson();
  1. 修改控制器方法:
[HttpGet("GetMixedJson")]
public IActionResult GetMixedJson()
{
    string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    // 直接转换为JArray,避免先序列化字符串再解析,节省内存
    JArray jsonArray = JArray.FromObject(Summaries);

    JObject jsonObject = new JObject();
    jsonObject["thisFiledValueWillBeMissing"] = "JObject will serialize correctly :)";

    var resultObject = new
    {
        PlainCSharpFiled = "plain c# fields showing fine",
        JsonObject = jsonObject,
        TunneledJson = jsonArray
    };

    return new JsonResult(resultObject);
}

如果必须使用已有的JSON字符串,可解析为JToken再加入结果:

string json = JsonConvert.SerializeObject(Summaries, Formatting.Indented);
JToken jsonToken = JToken.Parse(json);

方案二:使用System.Text.Json的JsonElement替代JObject(无需切换序列化库)

保留默认System.Text.Json序列化器,用JsonElement处理动态JSON结构:

[HttpGet("GetMixedJson")]
public IActionResult GetMixedJson()
{
    string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    // 将数组序列化为JsonElement,避免字符串编码
    using var doc = JsonDocument.Parse(JsonSerializer.Serialize(Summaries));
    JsonElement jsonElement = doc.RootElement.Clone();

    // 构建动态JSON对象
    var jsonObject = new Dictionary<string, object>
    {
        ["thisFiledValueWillBeMissing"] = "JsonElement works correctly"
    };

    var resultObject = new
    {
        PlainCSharpFiled = "plain c# fields showing fine",
        JsonObject = jsonObject,
        TunneledJson = jsonElement
    };

    return new JsonResult(resultObject);
}

方案三:直接写入响应流(最低内存开销,适合大数据量)

跳过中间对象构建,直接将JSON内容写入响应流,避免内存中生成完整JSON对象:

[HttpGet("GetMixedJson")]
public async Task GetMixedJson()
{
    string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    Response.ContentType = "application/json";
    await using var writer = new Utf8JsonWriter(Response.Body);

    writer.WriteStartObject();

    // 写入普通C#字段
    writer.WriteString("PlainCSharpFiled", "plain c# fields showing fine");

    // 写入动态JSON对象
    writer.WriteStartObject("JsonObject");
    writer.WriteString("thisFiledValueWillBeMissing", "Direct writing works");
    writer.WriteEndObject();

    // 直接写入数组,避免预序列化
    writer.WriteStartArray("TunneledJson");
    foreach (var summary in Summaries)
    {
        writer.WriteStringValue(summary);
    }
    writer.WriteEndArray();

    writer.WriteEndObject();
    await writer.FlushAsync();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:15:43