简体   繁体   English

如何使用GraphQL架构进行类似JSON Schema的数据验证?

[英]How to use a GraphQL schema for JSON Schema-like data validation?

We're looking into using GraphQL for version 2 of a headless CMS we're developing. 我们正在研究将GraphQL用于我们正在开发的无头CMS的第2版。

In version 1 of this CMS, we used JSON Schema to validate each document against a schema before being saved in the database -- for example, if it's a blog article it'd be validated against the Article schema, and if it's a roundup ("best of" list) it'd be validated against the Roundup schema. 在这个CMS的第1版中,我们使用JSON Schema在保存到数据库之前根据模式验证每个文档 - 例如,如果它是博客文章,它将根据Article模式进行验证,如果它是一个综合( “最好的”列表)它将根据Roundup架构进行验证。

For version 2, we're contemplating using GraphQL for the API. 对于版本2,我们正在考虑将GraphQL用于API。 And then it occurred to us that the GraphQL schema is basically parallel to the JSON Schema -- it describes the document structure, field types, etc. 然后我们发现GraphQL模式基本上与JSON模式并行 - 它描述了文档结构,字段类型等。

So we could simply have "one source of schema truth", the GraphQL schema, and use this both for querying documents and for validating new documents when a new revision is being saved. 因此,我们可以简单地使用“一个模式真实来源”,即GraphQL模式,并在保存新版本时使用它来查询文档和验证新文档。 (Note that I'm talking about validating JSON data against a GraphQL schema, not validating a GraphQL query against a schema.) (请注意,我正在讨论针对GraphQL架构验证JSON数据,而不是针对架构验证GraphQL查询。)

I figure the data would be validated against all the fields in the schema, except deprecated fields, because you only want to validate against the "latest version" of the fields. 我认为数据将针对架构中的所有字段进行验证,但已弃用的字段除外,因为您只想验证字段的“最新版本”。

We could do one of three things: 我们可以做以下三件事之一:

  1. Use the GraphQL AST directly to validate a document, ie, write a data validator ourselves. 直接使用GraphQL AST来验证文档,即自己编写数据验证器。
  2. Use the GraphQL AST to generate a JSON Schema, and use a standard JSON Schema validator to actually validate it. 使用GraphQL AST生成JSON模式,并使用标准JSON模式验证器来实际验证它。
  3. Just accept that GraphQL isn't quite the right fit for validation, and define the schema twice -- once in GraphQL for querying, and again in JSON Schema for validation (annoying and error-prone to keep them in sync). 只是接受GraphQL不太适合验证,并定义模式两次 - 一次在GraphQL中进行查询,再次在JSON Schema中进行验证(烦人且容易出错以保持同步)。

Questions: Are #1 and #2 silly ideas? 问题: #1和#2愚蠢的想法? Are there any GraphQL tools which do this kind of data validation? 是否有任何GraphQL工具可以进行这种数据验证? Are there any other ways to achieve this without defining the schema twice? 如果没有定义两次架构,还有其他方法可以实现吗?

For reference, our backend will be written in Python but the admin UI will be client-side React and JavaScript. 作为参考,我们的后端将用Python编写,但管理UI将是客户端的React和JavaScript。 This is a cut-down version of the kind of GraphQL schema we're talking about (supports "Article" and "Roundup" document types): 这是我们正在讨论的GraphQL架构的缩减版本(支持“Article”和“Roundup”文档类型):

schema {
    query: Query
}

type Query {
    documents: [Document!]!
    document(id: Int): Document!
}

interface Document {
    id: Int!
    title: String!
}

type Article implements Document {
    id: Int!
    title: String!
    featured: Boolean!
    sections: [ArticleSection!]!
}

union ArticleSection = TextSection | PhotoSection | VideoSection

type TextSection {
    content: String!
    heading: String
}

type PhotoSection {
    sourceUrl: String!
    linkUrl: String
    caption: String
    content: String
}

type VideoSection {
    url: String!
}

type Roundup implements Document {
    id: Int!
    title: String!
    isAward: Boolean!
    intro: String
    hotels: [RoundupHotel!]!
}

type RoundupHotel {
    url: String!
    photoUrl: String @deprecated(reason: "photoUrl is deprecated; use photos")
    photos: [RoundupPhoto!]!
    blurb: String!
    title: String
}

type RoundupPhoto {
    url: String!
    caption: String
}

Level of certainty in evolving situation 在不断变化的情况下的确定性水平

GraphQL is still an evolving technology ( as it says right at the top of the spec document ) so it's safe to say there are no truly "correct" answers for this. GraphQL仍然是一种不断发展的技术( 正如它在规范文档顶部所说的那样 ),因此可以肯定地说,没有真正“正确”的答案。

Generalities 泛泛而谈

InputObject types ("input" in Interface Definition Language terms) together with lists ("[]" in IDL terms) together with the various scalars seem to completely cover what you can do in JSON. InputObject类型(接口定义语言术语中的“输入”)与列表(IDL术语中的“[]”)以及各种标量似乎完全涵盖了您可以在JSON中执行的操作。

If the Python implementation of GraphQL conforms with the spec, then supplying data as either GraphQL literals or (better) as "variables" should provide everything that a custom validation could: GraphQL validation will do the right thing. 如果GraphQL的Python实现符合规范,那么提供数据作为GraphQL文字或(更好)作为“变量”应该提供自定义验证所能提供的一切:GraphQL验证将做正确的事情。

Recommendation for your situation 针对您的情况的建议

Based on my work with GraphQL so far, my suggestion is to "go with the grain". 根据我迄今为止使用GraphQL的工作,我的建议是“顺其自然”。 If your GraphQL schema conforms with what your data architecture requires, just use normal GraphQL validation. 如果您的GraphQL架构符合您的数据架构所需,只需使用普通的GraphQL验证。 If you do make your own validation, it should come after GraphQL has done its normal data-shape checking. 如果您确实进行了自己的验证,那么应该 GraphQL完成正常的数据形状检查之后进行验证。

To summarise the above points, and to answer your question with a question: what's wrong with letting GraphQL in its normal functioning do the validation heavy lifting? 总结以上几点,并用一个问题回答你的问题:让GraphQL正常运行有什么问题呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM