1

我有一个案例类Inventory

case class Inventory(
    organizationId: UUID,
    inventoryId: UUID,
    name: String,
    schema: String
)

输入类型:

private val NewInventoryInputType =
    deriveInputObjectType[Inventory](
        InputObjectTypeName("NewInventory"),
        ExcludeInputFields("organizationId", "inventoryId")
    )

一个论点:

val NewInventory = Argument("inventory", NewInventoryInputType)

最后是一个字段:

val MutationType = ObjectType("Mutation", fields[GraphQLContext, Unit](
    Field("createInventory", OptionType(UuidType),
        Some("Creates a new inventory."),
        NewInventory :: Nil,
        resolve = c => {
            val inventoryId = UUID.randomUUID
            val inventory = c arg NewInventory
            println(s"Inventory($inventory)")
            inventoryId
        }
    )
))

我想做的是能够Inventory用这样的查询创建一个:

{
    "query": "mutation ($inventory: NewInventory!) { createInventory(inventory: $inventory) }",
    "variables": {
        "inventory": {
            "name":"i1",
            "schema":"s"
        }
    }
}

缺少的部分是在Sangria 尝试使用它拥有的变量实例化域对象之前organizationId和之前创建 UUID 的位置。inventoryIdInventory

目前,我收到此错误:

Argument 'inventory' has invalid value: At path '/inventoryId': error.path.missing (line 1, column 67):
mutation ($inventory: NewInventory!) { createInventory(inventory: $inventory) }
                                                                  ^

(当然,我可以只创建一个NewInventory没有 ID 字段的案例类并Inventory手动实例化一个,但我想避免为每个实体类型创建和维护两个类。)

4

1 回答 1

0

当您为案例类定义输入对象时,您需要定义两件事:

  1. InputObjectType- 它在 GraphQL 模式中声明一个输入类型,并通过自省 API 公开它的元信息。在您的示例中,您在deriveInputObjectType[Inventory]宏的帮助下定义它。
  2. FromInput[Inventory]类型类的隐式实例- 它提供有关如何从某些输入(如 JSON)反序列化此输入对象的信息。正如您在其他地方提到的,您已经使用一些 JSON 库(Json.format[Inventory])定义它

由于您从输入对象的定义中排除了 2 个字段,因此您还需要确保反序列化器知道它,并且它应该能够处理缺少这 2 个字段的情况。在您的案例类中,这两个字段是非可选的,这意味着 JSON 库(我假设您正在使用play-json)将始终期望这两个字段存在。这就是您看到此错误的原因:Argument 'inventory' has invalid value: At path '/inventoryId'. 错误实际上来自play-json因为在 GraphQL Schema 中您允许该字段不存在但 JSON 反序列化器不知道它

FromInput[Inventory]虽然类型类提供了相当灵活的机制。我建议您检查它的文档,并可能定义您自己的实现/包装器来处理这些缺失的字段。另一种方法是更倾向于 CQRS并定义 2 种单独的模式:一种用于查询,另一种用于变异输入(也可以在 scala 代码中表示为 2 个单独的案例类)。当然,您也可以将两个可选字段都定义为Option[UUID].

于 2017-10-05T22:19:22.553 回答