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

.NET Core 3.1使用GraphQL Client(v3.2.1)调用API时响应Data属性为空问题

排查GraphQL Client返回Data为Null的问题

我之前也碰到过类似的情况,结合你的代码和响应数据来看,大概率是序列化配置不匹配或者忽略了GraphQL的错误响应导致的,下面一步步帮你排查解决:

第一步:先检查GraphQL响应是否包含错误

即使HTTP状态码是200 OK,GraphQL接口也可能返回errors字段(比如权限问题、查询语法错误等),这时候SendQueryAsync返回的结果里Data会是null,而Errors属性会有具体错误信息。你可以先修改代码打印错误:

var result = await graphQLClient.SendQueryAsync<Data>(request);
// 新增错误检查逻辑
if (result.Errors != null && result.Errors.Any())
{
    foreach (var error in result.Errors)
    {
        Console.WriteLine($"GraphQL Error: {error.Message}");
        // 如果有错误详情,也可以打印出来
        if (error.Extensions != null)
        {
            Console.WriteLine($"Error Details: {Newtonsoft.Json.JsonConvert.SerializeObject(error.Extensions)}");
        }
    }
}

如果这里输出了错误信息,直接根据提示修复即可(比如查询语句拼写错误、权限不足等)。

第二步:修复序列化的大小写映射问题

如果没有错误,那核心问题就是Newtonsoft.Json的序列化配置和你的模型类不匹配:

问题根源

GraphQL接口返回的是小驼峰命名的JSON字段,而你通过“粘贴JSON为类”生成的模型类也是小驼峰属性,但GraphQL Client默认的NewtonsoftJsonSerializer使用的是CamelCasePropertyNamesContractResolver——这个解析器的逻辑是:将C#的PascalCase属性映射到JSON的小驼峰字段。你的模型属性是小驼峰,就会导致映射失败,最终反序列化后Data为null。

解决方法(推荐遵循C#编码规范)

修改模型类为C#标准的PascalCase命名,然后显式配置序列化器使用驼峰解析:

1. 调整模型类为PascalCase

// 注意:不需要Rootobject类,因为SendQueryAsync会自动提取外层的data字段
public class Data 
{ 
    public CurrentUser CurrentUser { get; set; } 
}
public class CurrentUser 
{ 
    public int CardsCount { get; set; } 
    public Card[] Cards { get; set; } 
}
public class Card 
{ 
    public string Name { get; set; } 
    public string PictureUrl { get; set; } 
    public string Position { get; set; } 
    public Player Player { get; set; } 
}
public class Player 
{ 
    public string DisplayName { get; set; } 
}

2. 配置GraphQL Client的序列化器

创建GraphQLHttpClient时,传入自定义的Newtonsoft.Json配置:

var serializerSettings = new Newtonsoft.Json.JsonSerializerSettings
{
    // 让序列化器将JSON小驼峰映射到C# PascalCase属性
    ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
    // 忽略null值,避免不必要的序列化问题
    NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
};

var graphQLClient = new GraphQLHttpClient(
    new GraphQLHttpClientOptions { EndPoint = new Uri(_graphQLEndPoint) },
    new NewtonsoftJsonSerializer(serializerSettings),
    httpclient);

3. 调用时使用正确的泛型参数

因为SendQueryAsync<T>会自动解析响应中最外层的data字段,所以直接传入Data类作为泛型即可:

var request = new GraphQLRequest 
{ 
    Query = @"query CurrentUserCards { 
        currentUser { 
            cardsCount 
            cards { 
                name 
                pictureUrl 
                position 
                player { displayName } 
            } 
        } 
    }" 
};
var result = await graphQLClient.SendQueryAsync<Data>(request);
// 现在result.Data应该就是你要的CurrentUser数据了
var currentUser = result.Data.CurrentUser;

备选方案(保持现有小驼峰模型)

如果你不想修改模型类,可以改用默认的DefaultContractResolver,它会按名称(不区分大小写)匹配字段和属性:

var serializerSettings = new Newtonsoft.Json.JsonSerializerSettings
{
    ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver(),
    MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Ignore // 忽略JSON中存在但模型里没有的字段
};

var graphQLClient = new GraphQLHttpClient(
    new GraphQLHttpClientOptions { EndPoint = new Uri(_graphQLEndPoint) },
    new NewtonsoftJsonSerializer(serializerSettings),
    httpclient);

调用时同样使用Data类作为泛型参数即可。

额外注意点

  • 不要用Rootobject作为泛型参数:SendQueryAsync<T>已经帮你处理了最外层的data字段,传入Rootobject会导致它尝试将data字段反序列化为Rootobject类型,而实际data字段的结构是Data类,所以会出现嵌套错误。
  • 确认查询语句的字段名和模型属性完全对应:比如你的查询里是cardsCount,模型里要对应CardsCount(PascalCase)或者cardsCount(小驼峰),不能有拼写错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:28:11