We're looking into using GraphQL for version 2 of a headless CMS we're developing.
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.
For version 2, we're contemplating using GraphQL for the 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.
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. (Note that I'm talking about validating JSON data against a GraphQL schema, not validating a GraphQL query against a schema.)
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:
Questions: Are #1 and #2 silly ideas? Are there any GraphQL tools which do this kind of data validation? 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. This is a cut-down version of the kind of GraphQL schema we're talking about (supports "Article" and "Roundup" document types):
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
}
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.
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.
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.
Based on my work with GraphQL so far, my suggestion is to "go with the grain". If your GraphQL schema conforms with what your data architecture requires, just use normal GraphQL validation. If you do make your own validation, it should come after GraphQL has done its normal data-shape checking.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With