能否解释一下为什么如果变异的输入参数是对象它应该是输入类型?我认为更简单的只是重用类型而不提供id.
例如:
type Sample { id: String name: String } input SampleInput { name: String } type RootMutation { addSample(sample: Sample): Sample # <-- instead of it should be addSample(sample: SampleInput): Sample }
对于小对象来说没问题,但是当你有很多对象在模式中有10多个属性时会成为负担.
杰西的评论是正确的.有关更正式的答案,以下是有关输入类型的GraphQL文档的摘录:
上面定义的Object类型不适合在这里重用,因为Objects可以包含表示循环引用或对接口和联合的引用的字段,这两个字段都不适合用作输入参数.因此,输入对象在系统中具有单独的类型.
发布之后,我发现循环引用实际上是可以接受的,只要它们是可以接受的(或者它会声明一个无限链).但是,仍有其他限制(例如接口)似乎需要一个单独的输入类型系统.
从规格:
GraphQL对象类型(ObjectTypeDefinition)...不适合重复使用[作为输入],因为对象类型可以包含定义参数的字段或包含对接口和联合的引用,这两种都不适合用作输入参数。因此,输入对象在系统中具有单独的类型。
这是“官方原因”,但是有几个实际原因导致您不能将对象类型用作输入对象类型或将对象类型用作输入对象类型:
对象类型和输入对象类型都有字段,但是这些字段具有不同的属性,这些属性反映了模式如何使用这些类型。模式可能会为对象类型的字段定义参数和某种解析器功能,但是这些属性在输入上下文中没有意义(即,您无法解析输入对象的字段-它已经具有显式值) 。同样,只能为输入对象类型字段提供默认值,而不能为对象类型字段提供默认值。
换句话说,这似乎是重复的:
type Student { name: String grade: Grade } input StudentInput { name: String grade: Grade }
但是添加特定于对象类型或输入对象类型的功能可以清楚地表明它们的行为有所不同:
type Student { name(preferred: Boolean): String grade: Grade } input StudentInput { name: String grade: Grade = F }
GraphQL中的类型分为输出类型和输入类型。
输出类型是可以作为GraphQL服务生成的响应的一部分返回的类型。输入类型是作为字段或指令参数的有效输入的类型。
这两组之间有重叠(即标量,枚举,列表和非空值)。但是,诸如联合和接口之类的抽象类型在输入上下文中没有意义,因此不能用作输入。将对象类型和输入对象类型分开可以确保在需要输入类型的地方永远不要使用抽象类型。
在模式中表示实体时,某些实体可能确实会在其各自的输入和输出类型之间“共享字段”:
type Student { firstName: String lastName: String grade: Grade } input StudentInput { firstName: String lastName: String grade: Grade }
但是,对象类型可以(实际上经常这样做)为非常复杂的数据结构建模:
type Student { fullName: String! classes: [Class!]! address: Address! emergencyContact: Contact # etc }
尽管这些结构可能会转换为适当的输入(我们创建了一个Student,所以我们也传递了一个表示其地址的对象),但通常它们却没有这样做-即,也许我们需要通过班级ID和科目ID指定学生的班级,而不是宾语。同样,我们可能有想要返回但不想突变的password
字段,反之亦然(例如,字段)。
而且,即使对于相对简单的实体,我们也常常对对象类型与其“对应”输入对象之间的可空性有不同的要求。通常,我们想保证在响应中也将返回一个字段,但是我们不想输入相同的字段。例如,
type Student { firstName: String! lastName: String! } input StudentInput { firstName: String lastName: String }
最后,在许多模式中,给定实体的对象类型和输入对象类型之间通常没有一对一的映射。一种常见的模式是将单独的输入对象类型用于不同的操作,以进一步微调架构级别的输入验证:
input CreateUserInput { firstName: String! lastName: String! email: String! password: String! } input UpdateUserInput { email: String password: String }
所有这些示例都说明了一个重点-尽管输入对象类型有时可能会映射对象类型,但是由于业务需求,您在生产模式中看到该对象的可能性要小得多。