首页 文章

GraphQL ObjectType,包含基于参数的动态字段

提问于
浏览
9

我们的情况是GraphQL Query的响应必须返回对象的一些动态属性 . 在我们的例子中,我们无法预定义所有可能的属性 - 因此它必须是动态的 .

我们认为有两种方法可以解决它 .

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      /*
      THIS is our special field which needs to return a dynamic object 
      */
    },
    // ...
  },
});

正如您在示例代码中看到的那样,元素是必须返回对象的属性 . 解决此问题时的响应可能是:

{
  name: 'some name',
  elements: {
    an_unkonwn_key: {
      some_nested_field: {
        some_other: true,
      },
    },
    another_unknown_prop: 'foo',
  },
}

1) Return a "Any-Object"

我们可以返回任何对象 - 因此GraphQL不需要知道Object有哪些字段 . 当我们告诉GraphQL该字段是GraphQlObjectType类型时,它需要定义字段 . 因此,似乎无法告诉GraphQL某人只是一个对象 .

我们已经改变了这个:

elements: {
      type: new GraphQLObjectType({ name: 'elements' });
    },

2) We could define dynamic field properties because its in an function

当我们将字段定义为函数时,我们可以动态地定义对象 . 但是字段函数需要一些信息(在我们的例子中,信息将被传递给元素),我们需要访问它们来构建字段对象 .

例:

const MyType = new GraphQLObjectType({
  name: 'SomeType',
  fields: {
    name: {
      type: GraphQLString,
    },
    elements: {
      type: new GraphQLObjectType({
        name: 'elements',
        fields: (argsFromElements) => {
          // here we can now access keys from "args"
          const fields = {};
          argsFromElements.keys.forEach((key) => {
            // some logic here ..
            fields[someGeneratedProperty] = someGeneratedGraphQLType;
          });
          return fields;
        },
      }),
      args: {
        keys: {
          type: new GraphQLList(GraphQLString),
        },
      },
    },
    // ...
  },
});

这可能有效,但问题是如果有办法将args和/或解析对象传递给字段 .

Question 所以现在我们的问题是:在我们的GraphQL案例中推荐哪种方式,解决方案1或2是否可行?也许有另一种解决方案?

Edit 使用ScalarType时,解决方案1可以正常工作 . 例:

type: new GraphQLScalarType({
        name: 'elements',
        serialize(value) {
          return value;
        },
      }),

我不确定这是否是一种解决我们情况的推荐方法 .

1 回答

  • 9

    这两种选择都不可行:

    • GraphQL是强类型的 . GraphQL.js不支持某种 any 字段,并且架构中定义的所有类型都必须定义字段 . If you look in the docsfields 是必需的 - 如果您尝试将其删除,您将遇到错误 .

    • Args用于基于每个请求解析查询 . 您无法将它们传递回您的架构 . 您的架构应该是静态的 .

    正如你的建议,它通过滚动你自己的客户Scalar来重新尝试 . 我认为更简单的解决方案就是使用JSON - 您可以导入custom scalar for it like this one . 然后让您的 elements 字段解析为包含动态字段的JSON对象或数组 . 如果需要,您还可以根据参数操作解析程序内的JSON对象(例如,如果要将返回的字段限制为args中定义的子集) .

    Word of warning: 利用JSON或包含嵌套数据的任何自定义标量的问题在于,您可以灵活地请求实际需要的内容 . 它还会导致客户端上有用的错误 - 我存在或返回null when I make the request 而不是稍后发现我得到的JSON blob没有包含我期望它的字段 .

相关问题