How to use a GraphQL schema for JSON Schema-like data validation? : <p>We're looking into using GraphQL for version 2 of a headless CMS we're developing.</p>

<p>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 <code>Article</code> schema, and if it's a roundup ("best of" list) it'd be validated against the <code>Roundup</code> schema.</p>

<p>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.</p>

<p>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.)</p>

<p>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.</p>

<p>We could do one of three things:</p>

<ol>
<li>Use the GraphQL AST directly to validate a document, i.e., write a data validator ourselves. </li>
<li>Use the GraphQL AST to generate a JSON Schema, and use a standard JSON Schema validator to actually validate it.</li>
<li>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).</li>
</ol>

<p><strong>Questions:</strong> 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?</p>

<p>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):</p>

<pre><code>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
}
</code></pre>
