GraphQL - 从嵌套的 JSON 对象中获取所有字段

Posted

技术标签:

【中文标题】GraphQL - 从嵌套的 JSON 对象中获取所有字段【英文标题】:GraphQL - Get all fields from nested JSON object 【发布时间】:2016-08-31 18:26:15 【问题描述】:

如Zero to GraphQL in 30 minutes 中所述,我在现有的 REST API 上放置了一个 GraphQL 包装器。我有一个产品的 API 端点,该端点具有一个指向嵌套对象的属性:

// API Response

  entity_id: 1,
  nested_object: 
    key1: val1,
    key2: val2,
    ...
  

是否可以定义架构,以便我可以在不显式定义嵌​​套对象及其所有属性的情况下获取整个嵌套对象?我希望我的查询只指定我想要嵌套对象,而不需要从嵌套对象中指定我想要的所有属性:

// What I want

  product(id: "1") 
    entityId
    nestedObject
  


// What I don't want

  product(id: "1") 
    entityId
    nestedObject 
      key1
      key2
      ...
    
  

我可以做第二个版本,但它需要很多额外的代码,包括创建NestedObjectType 并指定所有嵌套属性。我还想出了如何自动获取所有键的列表,如下所示:

const ProductType = new GraphQLObjectType(
  ...

  fields: () => (
    nestedObject: 
      type: new GraphQLList(GraphQLString),
      resolve: product => Object.keys(product.nested_object)
    
  )
)

不过,我还没有找到自动返回整个对象的方法。

【问题讨论】:

AFAIK,提供整个嵌套对象而不明确指定其字段目前在 GraphQL 中是不可行的。这有点违背 GraphQL 的原则,该原则旨在仅提供所需/请求的数据片段,而不是一次提供所有数据。您应该认真考虑使用 GraphQL 的动机。如果您担心移动数据带宽,它可能是一个不错的选择。 感谢您的回复。我只是为了学习目的而玩弄它。我想可能是这样。对我来说,这对于***查询是有意义的,但对于嵌套对象来说意义不大。在组件中,我只想遍历嵌套对象中的所有内容 - 似乎如果在服务器上的该对象中添加了某些内容,客户端不需要担心它。我想如果你使用 GraphQL 作为主要 api 而不是包装现有的 REST api,这个问题会更容易避免。 "似乎如果在服务器上的那个对象上添加了一些东西,客户端应该不需要担心它。"您是指基于推送的通知/更新(从服务器到客户端)吗? 不,我的意思是更改代码 - 如果您向服务器上的对象添加新密钥,您似乎也不需要更新客户端的代码。客户端要做的只是显示嵌套对象中的每个键值对,它不需要知道这些键被称为什么。 目前无法在服务器端获取新引入的数据而无需在客户端进行修改。如果nested_object 不再有嵌套对象作为值,那么您可以尝试一个丑陋的替代方案 - 将nested_object 定义为字符串数组,其中第一个元素是键,下一个是它的值,依此类推。这样,数组可以任意长,并且您的 nested_object 变得灵活 w.r.t.在服务器端更改。 【参考方案1】:

我可以做第二个版本,但是它需要很多额外的代码,包括创建一个 NestedObjectType 和指定所有的嵌套属性。

去做吧!这将会非常棒。这是充分发挥 GraphQL 潜力的方法。

除了防止过度获取之外,它还为您提供了许多其他好处,例如类型验证,以及更易读和可维护的代码,因为您的架构可以更全面地描述您的数据。稍后您会感谢自己提前完成的额外工作。

如果由于某种原因您真的不想走这条路并完全理解后果,您可以使用JSON.stringify 将嵌套对象编码为字符串。

但就像我说的,我建议你不要这样做!

【讨论】:

【参考方案2】:

您可以尝试使用标量 JSON 类型。你可以找到更多here (based on apollographql)。

scalar JSON 添加到架构定义中; 将JSON: GraphQLJSON 添加到解析函数中; 在 shema 中使用 JSON 类型:

    scalar JSON
    type Query 
        getObject: JSON
    

查询示例:

    query 
      getObject
    

结果:

    
      "data": 
        "getObject": 
          "key1": "value1",
          "key2": "value2",
          "key3": "value3"
        
      
    

基本代码:


    const express = require("express");
    const graphqlHTTP = require("express-graphql");
    const  buildSchema  = require("graphql");
    const GraphQLJSON = require("graphql-type-json");

    const schema = buildSchema(`
      scalar JSON

      type Query 
        getObject: JSON
      
    `);

    const root = 
      JSON: GraphQLJSON,

      getObject: () => 
        return 
          key1: "value1",
          key2: "value2",
          key3: "value3"
        ;
      
    ;

    const app = express();
    app.use(
      "/graphql",
      graphqlHTTP(
        schema: schema,
        rootValue: root,
        graphiql: true
      )
    );
    app.listen(4000);
    console.log("Running a GraphQL API server at localhost:4000/graphql");

【讨论】:

以上是关于GraphQL - 从嵌套的 JSON 对象中获取所有字段的主要内容,如果未能解决你的问题,请参考以下文章

使用嵌套对象获取 React 中 Graphql 的问题 - 对象未定义

如何通过 ID 从 Apollo 缓存中读取嵌套对象?

使用 System.Text.Json 获取嵌套属性

从嵌套的 json 值对象中获取数组

如何从 REST API 定义多个或嵌套 json 数据的数组类型

无法从 json-server 获取嵌套的对象数组