如何将 JSON 的 HTTP post 简化为 GraphQL 突变解析器
How to simplify HTTP post of JSON to GraphQL mutation resolver
我想将 POST 值直接作为 JSON 发送到已在我的 GraphQL 突变中声明的 addBook 解析器。
但是,我看到(并证明)的示例使用从 JSON 到 SDL 的参数序列化或在 SDL 中重新声明变量以从查询变量绑定。
这两种方法都没有意义,因为 addBook 突变已经声明了所有参数和验证。使用这些方法将导致必须创建、调试和维护不必要的查询序列化逻辑。
我在浏览器中构造了格式良好的(模式编辑和验证)JSON,它符合声明的 GraphQLObjectType 的数据。
任何人都可以解释在post针对突变解析器时如何避免这种不必要的重新序列化或重复吗?
我一直在尝试使用多种方法将 JSON 数据结构映射到 addBook 突变,但找不到简单发送 JSON 以便 属性 的示例名称与 addBook 参数名称绑定,没有明显无意义的重新序列化或样板文件。
https://github.com/cefn/graphql-gist/tree/master/mutation-map 处的源代码是一个最小的可重现示例,它演示了该问题。它有一个 addBook 解析器,它已经定义了参数名称、类型和可空性。我找不到使用 JSON 来简单地针对 addBook POST 参数的方法。
我使用 GraphiQL 作为 HTTP POST 值的参考实现。
我可以编写代码将 JSON 序列化为 SDL。它最终看起来像这样通过 GraphiQL 工作:
mutation {addBook(id:"4", name:"Education Course Guide", genre: "Education"){
id
}}
或者我可以编写代码将 addBook 的每个参数显式别名到不同的查询,然后允许我将 post 值作为 JSON 查询变量,也通过 GraphiQL 证明:
mutation doAdd($id: String, $name: String!, $genre: String){
addBook(id:$id, name:$name, genre:$genre){
id
}
}
...使用查询变量...
{
name: "Jonathan Livingstone Seagull",
id: "6"
}
但是,我确信有一些方法可以直接 post 这个 JSON 针对 addBook,告诉它从查询变量中获取参数。我在想像...
mutation {addBook($*){
id
}}
我希望对 addBook 的突变调用成功,从 JSON 查询变量中获取命名值,但不将属性重新序列化或重新声明为参数名称。
这归结为模式设计。而不是在你的领域有三个参数
type Mutation {
addBook(id: ID, name: String!, genre: String!): Book
}
您可以有一个接受输入对象类型的参数
type Mutation {
addBook(input: AddBookInput!): Book
}
input AddBookInput {
id: ID
name: String!
genre: String!
}
那么您的查询只需提供一个变量:
mutation AddBook($input: AddBookInput!) {
addBook(input: $input) {
id
}
}
你的变量看起来像:
{
"input": {
"name": "Jonathan Livingstone Seagull",
"genre": "Fable"
}
}
变量必须明确定义为操作定义的一部分,因为 GraphQL 和 JSON 不可互换。 JSON 字符串值可以是字符串、ID 或 GraphQL 中的一些自定义标量(如 DateTime)。变量定义告诉 GraphQL 如何正确序列化和验证提供的 JSON 值。因为变量可以在整个文档中多次使用,所以它们的类型同样不能简单地从它们所使用的参数的类型中推断出来。
编辑:
每个文档只声明一次变量。一旦声明,它们可能会在整个文档中被多次提及。想象一下像
这样的查询
mutation MyMutation ($id: ID!) {
flagSomething(somethingId: $id)
addPropertyToSomething(id: $id, property: "WOW")
}
我们声明变量一次并告诉 GraphQL 它是一个 ID 标量并且它是不可空的(即必需的)。然后我们两次使用该变量——一次作为 flagSomething
上 somethingId
的值,另一次作为 addPropertyToSomething
上 id
的值。同样的变量也可以用作指令参数的值——它不仅限于字段参数。还要注意,没有说变量名必须与字段名匹配——这通常只是出于方便。
另一个值得注意的事情是这里发生了两个验证步骤。
首先,GraphQL 将检查提供的变量(即 JSON 值)是否可以序列化为指定的类型。由于我们将变量声明为非 null(使用 !
),GraphQL 还将验证变量是否实际存在并且不等于 null。
GraphQL 还将验证您为变量指定的类型是否与实际使用的参数类型相匹配。因此,如果将 Int 变量传递给 String 参数等,它将抛出异常。此外,这里也检查了可空性。因此,作为 Int!
(非空整数)的参数将只接受也是 Int!
的变量。但是,Int
(即可为空)的参数将接受 Int
或 Int!
变量。
存在的语法是有原因的。您想象的那种语法仅在您仅查询单个根字段 和 使用所有变量作为该字段的参数的特定场景中才有意义 and 变量名称与参数名称匹配 and 你不需要动态设置任何指令参数。
我想将 POST 值直接作为 JSON 发送到已在我的 GraphQL 突变中声明的 addBook 解析器。
但是,我看到(并证明)的示例使用从 JSON 到 SDL 的参数序列化或在 SDL 中重新声明变量以从查询变量绑定。
这两种方法都没有意义,因为 addBook 突变已经声明了所有参数和验证。使用这些方法将导致必须创建、调试和维护不必要的查询序列化逻辑。
我在浏览器中构造了格式良好的(模式编辑和验证)JSON,它符合声明的 GraphQLObjectType 的数据。
任何人都可以解释在post针对突变解析器时如何避免这种不必要的重新序列化或重复吗?
我一直在尝试使用多种方法将 JSON 数据结构映射到 addBook 突变,但找不到简单发送 JSON 以便 属性 的示例名称与 addBook 参数名称绑定,没有明显无意义的重新序列化或样板文件。
https://github.com/cefn/graphql-gist/tree/master/mutation-map 处的源代码是一个最小的可重现示例,它演示了该问题。它有一个 addBook 解析器,它已经定义了参数名称、类型和可空性。我找不到使用 JSON 来简单地针对 addBook POST 参数的方法。
我使用 GraphiQL 作为 HTTP POST 值的参考实现。
我可以编写代码将 JSON 序列化为 SDL。它最终看起来像这样通过 GraphiQL 工作:
mutation {addBook(id:"4", name:"Education Course Guide", genre: "Education"){
id
}}
或者我可以编写代码将 addBook 的每个参数显式别名到不同的查询,然后允许我将 post 值作为 JSON 查询变量,也通过 GraphiQL 证明:
mutation doAdd($id: String, $name: String!, $genre: String){
addBook(id:$id, name:$name, genre:$genre){
id
}
}
...使用查询变量...
{
name: "Jonathan Livingstone Seagull",
id: "6"
}
但是,我确信有一些方法可以直接 post 这个 JSON 针对 addBook,告诉它从查询变量中获取参数。我在想像...
mutation {addBook($*){
id
}}
我希望对 addBook 的突变调用成功,从 JSON 查询变量中获取命名值,但不将属性重新序列化或重新声明为参数名称。
这归结为模式设计。而不是在你的领域有三个参数
type Mutation {
addBook(id: ID, name: String!, genre: String!): Book
}
您可以有一个接受输入对象类型的参数
type Mutation {
addBook(input: AddBookInput!): Book
}
input AddBookInput {
id: ID
name: String!
genre: String!
}
那么您的查询只需提供一个变量:
mutation AddBook($input: AddBookInput!) {
addBook(input: $input) {
id
}
}
你的变量看起来像:
{
"input": {
"name": "Jonathan Livingstone Seagull",
"genre": "Fable"
}
}
变量必须明确定义为操作定义的一部分,因为 GraphQL 和 JSON 不可互换。 JSON 字符串值可以是字符串、ID 或 GraphQL 中的一些自定义标量(如 DateTime)。变量定义告诉 GraphQL 如何正确序列化和验证提供的 JSON 值。因为变量可以在整个文档中多次使用,所以它们的类型同样不能简单地从它们所使用的参数的类型中推断出来。
编辑:
每个文档只声明一次变量。一旦声明,它们可能会在整个文档中被多次提及。想象一下像
这样的查询mutation MyMutation ($id: ID!) {
flagSomething(somethingId: $id)
addPropertyToSomething(id: $id, property: "WOW")
}
我们声明变量一次并告诉 GraphQL 它是一个 ID 标量并且它是不可空的(即必需的)。然后我们两次使用该变量——一次作为 flagSomething
上 somethingId
的值,另一次作为 addPropertyToSomething
上 id
的值。同样的变量也可以用作指令参数的值——它不仅限于字段参数。还要注意,没有说变量名必须与字段名匹配——这通常只是出于方便。
另一个值得注意的事情是这里发生了两个验证步骤。
首先,GraphQL 将检查提供的变量(即 JSON 值)是否可以序列化为指定的类型。由于我们将变量声明为非 null(使用 !
),GraphQL 还将验证变量是否实际存在并且不等于 null。
GraphQL 还将验证您为变量指定的类型是否与实际使用的参数类型相匹配。因此,如果将 Int 变量传递给 String 参数等,它将抛出异常。此外,这里也检查了可空性。因此,作为 Int!
(非空整数)的参数将只接受也是 Int!
的变量。但是,Int
(即可为空)的参数将接受 Int
或 Int!
变量。
存在的语法是有原因的。您想象的那种语法仅在您仅查询单个根字段 和 使用所有变量作为该字段的参数的特定场景中才有意义 and 变量名称与参数名称匹配 and 你不需要动态设置任何指令参数。