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

C#中使用dynamic时如何正确反序列化JSON对象?

问题原因及解决方案

核心问题

你使用的SystemTextJsonSerializer在处理dynamic类型时,会将GraphQL响应的JSON反序列化为JsonElement对象——这是System.Text.Json的JSON DOM节点类型,直接输出或序列化时就会显示{"ValueKind":"Object"},而非实际的JSON数据内容。


解决方案

方案1:换用NewtonsoftJsonSerializer(最简便)

Newtonsoft.Json对dynamic的支持更贴合预期,它会将JSON转换为JObject,可以直接正常序列化或传递给前端。

首先安装NuGet包:GraphQL.Client.Serializer.Newtonsoft,然后修改执行器代码:

public async Task<T> ExecuteGQlQuery<T>(string url, string reqQuery, AuthenticationHeaderValue credentials, object variables)
{
    try
    {
        // 替换为Newtonsoft序列化器
        var graphQLClient = new GraphQLHttpClient(url, new NewtonsoftJsonSerializer());
        graphQLClient.HttpClient.DefaultRequestHeaders.Authorization = credentials;

        var gQLRequest = new GraphQLRequest
        {
            Query = reqQuery,
            Variables = variables
        };

        var response = await graphQLClient.SendQueryAsync<T>(gQLRequest);

        return response.Data;
    }
    catch (Exception)
    {
        throw;
    }
}

之后调用ExecuteGQlQuery<dynamic>时,返回的JObject可以直接序列化为正确的JSON内容转发给前端。

方案2:手动转换JsonElement(不更换序列化器)

如果不想更换序列化器,可以将返回的JsonElement(即你用dynamic接收的对象)手动转换为可用的动态对象或直接获取原始JSON字符串:

转换为动态对象
// 明确指定返回类型为JsonElement
var rawElement = await _executeService.ExecuteGQlQuery<JsonElement>(myUrl, query, credentials, null);
// 反序列化为ExpandoObject作为dynamic使用
dynamic data = JsonSerializer.Deserialize<ExpandoObject>(rawElement);
直接返回原始JSON字符串

给执行器添加一个重载方法:

public async Task<string> ExecuteGQlQueryRaw(string url, string reqQuery, AuthenticationHeaderValue credentials, object variables)
{
    try
    {
        var graphQLClient = new GraphQLHttpClient(url, new SystemTextJsonSerializer());
        graphQLClient.HttpClient.DefaultRequestHeaders.Authorization = credentials;

        var gQLRequest = new GraphQLRequest
        {
            Query = reqQuery,
            Variables = variables
        };

        // 直接获取原始响应内容
        var responseMessage = await graphQLClient.HttpClient.PostAsJsonAsync("", gQLRequest);
        responseMessage.EnsureSuccessStatusCode();
        return await responseMessage.Content.ReadAsStringAsync();
    }
    catch (Exception)
    {
        throw;
    }
}

调用这个重载就能拿到原始JSON字符串,直接转发给前端即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:20:41