我们如何递归地自省 GraphQL 模式?

Posted

技术标签:

【中文标题】我们如何递归地自省 GraphQL 模式?【英文标题】:How can we introspect a GraphQL schema recursively? 【发布时间】:2018-06-26 01:30:50 【问题描述】:

如果客户不知道架构并且想自省和理解 GraphQL API,那么 GraphQL 似乎无法支持递归自省。关于我的观点,请参见以下示例

首先,以下是我在高层的架构定义:

// schema.js
...
...     
const AuthorType = new GraphQLObjectType(
  name: "Author",
  description: "This represent an author",
  fields: () => (
    id: type: new GraphQLNonNull(GraphQLString),
    name: type: new GraphQLNonNull(GraphQLString),
    twitterHandle: type: GraphQLString
  )
);

const PostType = new GraphQLObjectType(
  name: "Post",
  description: "This represent a Post",
  fields: () => (
    id: type: new GraphQLNonNull(GraphQLString),
    title: type: new GraphQLNonNull(GraphQLString),
    body: type: GraphQLString,
    author: 
      type: AuthorType,
      resolve: function(post) 
        return _.find(Authors, a => a.id == post.author_id);
      
    
  )
);

// This is the Root Query
const BlogQueryRootType = new GraphQLObjectType(
  name: 'BlogAppSchema',
  description: "Blog Application Schema Query Root",
  fields: () => (
    authors: 
      type: new GraphQLList(AuthorType),
      description: "List of all Authors",
      resolve: function() 
        return Authors
      
    ,
    posts: 
      type: new GraphQLList(PostType),
      description: "List of all Posts",
      resolve: function() 
        return Posts
      
    
  )
);

当有人使用以下查询子句查询架构时:


  __type(name: "BlogAppSchema") 
    name
    fields 
      name
      description
      type 
        name
      
    
  

她得到以下结果:


  "data": 
    "__type": 
      "name": "BlogAppSchema",
      "fields": [
        
          "name": "authors",
          "description": "List of all Authors",
          "type": 
            "name": null
          
        ,
        
          "name": "posts",
          "description": "List of all Posts",
          "type": 
            "name": null
          
        
      ]
    
  

阅读源码,我们知道作者是一个AuthorType的列表。但是没有访问源代码的用户如何从上面得到的结果中进一步内省“作者”字段(类型字段在这里显示“null”)?她似乎无法从上述结果中知道authorsAuthor 的列表。有没有办法让她进一步反省?

【问题讨论】:

【参考方案1】:

name 字段返回 null,因为您的 AuthorType 被 GraphQLList 包装器包装。这意味着该字段正在返回有关包装器的信息,而不是底层类型。要获取该类型,您需要修改您的请求:


  __type(name: "BlogAppSchema") 
    name
    fields 
      name
      description
      type 
        name
        kind # this will show NON_NULL, LIST, SCALAR or OBJECT
        ofType  # if NON_NULL or LIST what is it a non-null or list *of*
          name
          kind
          # other fields, like "fields" which will be populated for an OBJECT
        
      
    
  

如果您使用多个包装器(即 [Author]! 或 [Author!]!),您将需要“更深入”并请求嵌套的 ofType 字段:


  __type(name: "BlogAppSchema") 
    name
    fields 
      name
      description
      type 
        name
        kind 
        ofType  
          name
          kind
          ofType 
            name
            kind
            ofType 
              name
              kind
              ofType 
                name
                kind
              
            
          
        
      
    
  

如果kindOBJECT,则其fields 字段将被适当地填充。然后,您可以像上面一样请求每个字段的详细信息。当然,如果那些字段返回了任何 OBJECT,您必须指定要从这些字段中获取哪些信息。

你可以阅读更多关于自省的内容here。

内省可能非常混乱。如果您需要一种让 GraphQL 端点的使用者探索模式的方法,那么 GraphiQL 是一种更加用户友好的方式。还有动态生成文档的方法 (like this)。

【讨论】:

以上是关于我们如何递归地自省 GraphQL 模式?的主要内容,如果未能解决你的问题,请参考以下文章

中继应用程序:如何自省服务器上的模式?

/graphql 处的递归错误。超出最大递归深度

如何从 GraphQL 生成 Dart - graphql 到 dart 生成器

如何在 Graphql 中删除自省查询的身份验证

Apollo GraphQL 客户端查询返回自省结果而不是数据

GraphQL 架构文件应包含有效的 GraphQL 自省查询结果