如何使用Sangria为在GraphQL中创建的实体提供ID?

时间:2017-10-03 20:16:57

标签: scala graphql sangria

我的案例类为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域对象之前为inventoryIdInventory创建UUID的位置。

目前,我收到此错误:

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

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