使用模式保留GraphQL响应的类型保留反序列化

时间:2020-06-29 14:01:33

标签: java graphql json-deserialization graphql-java

我正在尝试为用户定义的GraphQL查询的响应编写反序列化代码。该代码可以访问JSON序列化形式的查询响应和基础的GraphQL模式(通过查询端点的schema.json或发出自省请求)。

假定以下架构:

scalar Date

type User {
    name: String
    birthday: Date
}

type Query {
    allUsers: [User]
}

schema {
    query: Query
}

以及以下查询:

query {
    allUsers {
        name
        birthday
    }
}

响应可能看起来像这样(为简洁起见,仅包括完整响应中的data.allUsers字段):

[
    {"name": "John Doe", "birthday": "1983-12-07"}
]

我正在尝试以保留类型信息(包括任何自定义标量)的方式反序列化上述响应。在上面的示例中,按照惯例,我知道GraphQL标量Date在Java中应反序列化为LocalDate,但是仅从响应中我就不知道birthday字段表示GraphQL标量类型Date,因为它已序列化为JSON中的常规字符串。

可以要做的是尝试利用GraphQL模式。对于上面的示例,该架构可能类似于以下内容(为简洁起见而缩短):

...
"types": [
{
  "kind": "OBJECT",
  "name": "User",
  "fields": [
    {
      "name": "name",
      "type": {
        "kind": "SCALAR",
        "name": "String"
      }
    },
    {
      "name": "birthday"
      "type": {
        "kind": "SCALAR",
        "name": "Date"
      }
    }
...

根据这些信息,我可以推断出该响应的birthday字段的类型为Date,并相应地对其进行反序列化。但是,如果查询使用非平凡的GraphQL功能,事情就会变得更加复杂。以别名为例:

query {
    allUsers {
        name
        dayOfBirth: birthday
    }
}

在这一点上,我已经需要跟踪任何别名(我可以这样做,因为如果我解析查询,该信息就可用),然后回溯那些别名以找到正确的类型。我担心如果例如使用碎片。

鉴于我使用了graphql-java,并且看来已经需要处理所有这些情况以进行序列化,我想知道是否有比手动回溯更简便的方法查询和架构中的类型。

2 个答案:

答案 0 :(得分:1)

如何从架构中生成Java类,然后使用这些类进行反序列化。我以前曾为此使用过一个插件-graphql-java-generator

您可能需要对插件进行一些增强,以支持您的自定义标量

它基本上会生成一个Java客户端,以Java方式调用您的GraphQL查询。

答案 1 :(得分:0)

我在反序列化 LocalDate 属性时遇到了同样的问题,即使使用 graphql-java-extended-scalars 库也是如此。

经过研究,我发现这个库适用于查询,但不适用于突变。

我通过自定义 SchemaParserOptions 解决了我的问题,如下所示:

@Bean
public SchemaParserOptions schemaParserOptions() {
    return SchemaParserOptions.newOptions().objectMapperConfigurer((mapper, context) -> {
        mapper.registerModule(new JavaTimeModule());
    }).build();
}

在对象中我没有使用任何序列化和反序列化注释。

相关问题