GraphQL 无法解析嵌套对象属性

Posted

技术标签:

【中文标题】GraphQL 无法解析嵌套对象属性【英文标题】:GraphQL unable to resolve nested object property 【发布时间】:2017-01-07 08:32:53 【问题描述】:

我正在尝试返回一个带有列表中一些嵌套属性对象的 graphQL 查询。一切似乎都检查过了,但得到的是空值。

预期的数据结构响应(有关结构here 的更多详细信息):

//Return a GraphQLList type of all objects :    
[
    
        "subscription" : 

        ,
        "customer" : 

        ,
    ,
]

查询: subscriptions subscription id customer_id

GraphQL 查询对象:

var Query = new graphQL.GraphQLObjectType(
    name: 'Query',
    description: 'Root of the Schema',
    fields: 
        subscriptions: 
            type: new graphQL.GraphQLList(SubscriptionsList),
            args : 
                customer_name:  type: graphQL.GraphQLString ,
                customer_id:  type: graphQL.GraphQLString 
            ,
            resolve : function (source, args) 
                return getSubscriptions().then(function (res) 
                    // Shows that data is returned
                    console.log('Data: ', res.list);

                    return res.list;
                ).catch(function (err) 
                    return err;
                );
            
        
    
);

期望返回类型 GraphQLList of SubscriptionsList

var SubscriptionsList = new graphQL.GraphQLObjectType(
    name : 'SubscriptionObj',
    description : 'stuff',
    fields : function () 
        return 
            subscription : 
                type : Subscription,
                resolve : function (subscription) 
                    return  subscription;
                
            
        
    
);

应该解析嵌套字段属性:

var Subscription = new graphQL.GraphQLObjectType(
    name : 'Subscription',
    description : 'stuff',
    fields : function () 
        return 
            id: type: graphQL.GraphQLString,
            customer_id: type: graphQL.GraphQLString
        
    
);

Console.log(res.list) 输出(来自查询):我肯定得到了我期望的数据和结构:

[  subscription: 
      id: 'cbdemo_lloyd-sub2',
       customer_id: 'cbdemo_lloyd',
       plan_id: 'cbdemo_nuts',
       addons: [Object],
       due_invoices_count: 0,
       shipping_address: [Object] ,
    customer: 
       ...
    
  ,
  ...
]

GraphQL 查询输出:


  "data": 
    "subscriptions": [
      
        "subscription": 
          "id": null,
          "customer_id": null
        
      ,
      
        "subscription": 
          "id": null,
          "customer_id": null
        
      ,

EDIT 不是很必要,但这里是返回承诺的getSubscriptions() API 调用:

function getSubscriptions() 
    return new Promise(function (resolve, reject) 
        chargebee.subscription.list(
            limit : 5,
            "plan_id[is_not]" : "basic",
            "status[is]" : "active",
            "sort_by[asc]" : "created_at"
        ).request(function(error,result)
            if (error) return reject(error);
            return resolve(result);
        );
    );

【问题讨论】:

【参考方案1】:

根据您的帖子,res.list 显示以下内容:

// listing #1
[
   
    subscription: 
      id: 'cbdemo_lloyd-sub2',
      customer_id: 'cbdemo_lloyd',
      plan_id: 'cbdemo_nuts',
      addons: [Object],
      due_invoices_count: 0,
      shipping_address: [Object] ,
      customer: 
        ...
      
  ,
  ...
]

现在,上面的结果对应于Query 中的subscriptions 字段,这是SubscriptionsList 的列表。因此,SubscriptionsList 的值将是上述清单 #1 中的项目:

// listing #2

  subscription: 
    id: 'cbdemo_lloyd-sub2',
    customer_id: 'cbdemo_lloyd',
    plan_id: 'cbdemo_nuts',
    addons: [Object],
    due_invoices_count: 0,
    shipping_address: [Object] ,
    customer: 
      ...
    
  

SubscriptionsList 类型中,您有一个字段subscription。它的解析函数返回它得到的任何东西。因此,subscription 字段与清单 #2 保持一致。

在解析subscription 字段(类型Subscription)时,它会在清单#2 中显示的对象中查找idcustomer_id 属性。但该对象只有 subscription 属性。因此,idcustomer_id 字段接收 null 值。

因此,问题出在subscription 字段的解析函数中。它的输入是清单 #2 中的对象,其输出应该是以下清单 #3 中的对象:

// listing #3

  id: 'cbdemo_lloyd-sub2',
  customer_id: 'cbdemo_lloyd',
  plan_id: 'cbdemo_nuts',
  addons: [Object],
  due_invoices_count: 0,
  shipping_address: [Object] ,
  customer: 
    ...
  

要获取清单 #3 中的对象,请更改您的 SubscriptionsList 类型:

subscription : 
    type : Subscription,
    resolve : function (item)  // item is listing #2
        return  item.subscription; // item.subscription is listing #3
    

另一方面,GraphQL 对象类型SubscriptionsList 在这里实际上是不必要的,这使整个事情变得复杂。没有它,整个设计会变得简单很多。

【讨论】:

【参考方案2】:

我认为您的 SubscriptionsList 中的解析器必须返回 subscription.subscription。我会考虑更改subscriptionsList 的名称,因为它很混乱。

在我看来,您应该只拥有一个 GraphQLList(Subscription) 并删除额外的嵌套级别。要么这样,要么将包含订阅和客户的事物称为其他事物。

【讨论】:

【参考方案3】:

看起来你有点糊涂了, 基本上,当你设置

new graphQL.GraphQLList(SubscriptionsList),

这已经是一个列表。 这意味着你真正的意思是

new graphQL.GraphQLList(Subscription),

接下来,您的订阅对象不包含任何解析逻辑, 所以我希望它是这样的:

var Subscription = new graphQL.GraphQLObjectType(
    name : 'Subscription',
    description : 'stuff',
    fields : function () 
        return 
            id: 
                   type: graphQL.GraphQLString,
                   resolve: function(subscription) 
                       return subscription.subscription.id;
                   
            ,
            customer_id: 
                   type: graphQL.GraphQLString,
                   resolve: function(subscription) 
                       return subscription.subscription.customer_id;
                   
            ,
        
    
);

本质上发生的事情是,GraphQL 将使用 Subscription 对象解析提供的列表中的每个 javascript 对象。 每个解析器都会将 javascript 对象作为第一个值, 并从中返回基本值。

【讨论】:

小提示,如果你将console.log添加到Subscription的resolvers下,你应该能够看到列表中的每个对象,以确保你的方向是正确的 为什么我需要解析idcustomer_id?我的getSubscriptions() 方法在返回响应时不是已经解决了吗?为什么 GraphQL 需要解析这些字段? GraphQL 不知道如何处理对象。只有您为其定义的类型。基本上你是在声明一个新类型 Subscription ,然后你描述每个字段是如何解析的。这实际上是 GraphQL 的强大功能之一,因为 1 Object 不必与数据库层对象相同。更多信息可以找到here

以上是关于GraphQL 无法解析嵌套对象属性的主要内容,如果未能解决你的问题,请参考以下文章

Java / Hibernate:无法使用嵌套对象标准解析属性

GraphQL 解析器问题

GraphQL 嵌套查询返回 null

无法解析自定义对象 graphql 架构

“graphql-tools”中的嵌套解析器不起作用

NodeJs 中的 GraphQl - 对象类型的解析器