JSON Schema
JSON Schema is a declarative language for annotating and validating JSON documents' structure, constraints, and data types. It helps you standardize and define expectations for JSON data.
Installation
We can use JSON Schema directly in our project, or use typebox to help us build JSON Schema.
npm i @gqloom/core @gqloom/json
pnpm add @gqloom/core @gqloom/json
yarn add @gqloom/core @gqloom/json
bun add @gqloom/core @gqloom/json
Defining Simple Scalars
In GQLoom, you can use the jsonSilk
function to use a JSON Schema as a silk:
import { jsonSilk } from "@gqloom/json"
const StringScalar = jsonSilk({ type: "string" })
const BooleanScalar = jsonSilk({ type: "boolean" })
const FloatScalar = jsonSilk({ type: "number" })
const IntScalar = jsonSilk({ type: "integer" })
Defining Objects
When defining an object, you also need to wrap it with the jsonSilk
function:
import { jsonSilk } from "@gqloom/json"
const Cat = jsonSilk({
title: "Cat",
type: "object",
properties: {
name: { type: "string" },
age: { type: "integer" },
loveFish: { type: ["boolean", "null"] },
},
required: ["name", "age"],
})
Naming Objects
Note
Naming is optional in GQLoom
, and GQLoom
will automatically name objects based on operation names.
However, explicit naming is the recommended practice in most scenarios.
We can use the title
property of JSON Schema to name an object, as in the example code above; we can also use a __typename
literal to name it:
import { jsonSilk } from "@gqloom/json"
const Cat = jsonSilk({
type: "object",
properties: {
__typename: { const: "Cat" },
name: { type: "string" },
age: { type: "integer" },
loveFish: { type: ["boolean", "null"] },
},
required: ["name", "age"],
})
Defining Union Types
We can use the oneOf
property of JSON Schema to define a union type:
import { jsonSilk } from "@gqloom/json"
const Cat = jsonSilk({
title: "Cat",
type: "object",
properties: {
__typename: { const: "Cat" },
name: { type: "string" },
loveFish: { type: "boolean" },
},
})
const Dog = jsonSilk({
title: "Dog",
type: "object",
properties: {
__typename: { const: "Dog" },
name: { type: "string" },
loveBone: { type: "boolean" },
},
})
const Animal = jsonSilk({
title: "Animal",
oneOf: [Cat, Dog],
})
Defining Enum Types
We can use the enum
property of JSON Schema to define an enum type:
import { jsonSilk } from "@gqloom/json"
const Fruit = jsonSilk({
title: "Fruit",
description: "Some fruits you might like",
enum: ["apple", "banana", "orange"],
})
Custom Type Mapping
To accommodate more JSON Schema types, we can extend GQLoom by adding more type mappings.
First, we use JSONWeaver.config
to define the configuration for type mapping. Here we import the GraphQLDate
scalar from graphql-scalars. When a date
type is encountered, we map it to the corresponding GraphQL scalar.
import { JSONWeaver } from "@gqloom/json"
import { GraphQLDate } from "graphql-scalars"
const jsonWeaverConfig = JSONWeaver.config({
presetGraphQLType: (schema) => {
if (typeof schema === "object" && schema.format === "date")
return GraphQLDate
},
})
When weaving the GraphQL Schema, pass the configuration to the weave
function:
import { weave } from "@gqloom/json"
export const schema = weave(jsonWeaverConfig, helloResolver)
Default Type Mappings
The following table lists the default mappings between JSON Schema types and GraphQL types in GQLoom:
JSON Schema Property | GraphQL Type |
---|---|
{"type": "string"} | GraphQLString |
{"type": "number"} | GraphQLFloat |
{"type": "integer"} | GraphQLInt |
{"type": "boolean"} | GraphQLBoolean |
{"type": "object"} | GraphQLObjectType |
{"type": "array"} | GraphQLList |
{"enum": [...]} | GraphQLEnumType |
{"oneOf": [...]} | GraphQLUnionType |
{"anyOf": [...]} | GraphQLUnionType |