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
相关产品推荐
相关产品推荐

