How to set up JSON type in GraphQL Schema

02 March, 2024

2 min read

Last updated on 02 March, 2024

GraphQL was first introduced after Zalando was started as a tech company, so we have adopted GraphQL gradually as the majority of big companies out there. JSON type is the most frequent type people choose during migration period because they don’t want to spend time defining strict types and having overhead of strict typing during active development / transition period. 

I remember my colleagues in one of my previous companies were trying to implement everything through JSON type first assuming GraphQL is the same as REST, just with one endpoint.

via GIPHY

There is a common engineering proverb saying there is no more permanent solution than temporary one.

I would not argue if you should put JSON type in your schema or not. I would show you how to do that in case you already decided you want to do that.

Side note: At Zalando we prohibit usage of JSON type in schema. BUT we have legacy fields with JSON type and they are being used in production.

Result Demo

curl --location 'http://localhost:4000/graphql' \
--header 'Content-Type: application/json' \
--data '{"query":"query {\n    translations \n}","variables":{}}' | jq .

request for GraphQL API

{
  "data": {
    "translations": {
      "en": "Hello World",
      "fr": "Bonjour le monde"
    }
  }
}

response - translations field has JSON type and unstructured

Set Up

Base, minimalistic set up for GraphQL API server.

import express from "express";
import fs from "fs";
import { graphqlHTTP } from "express-graphql";
import {
  buildSchema,
} from "graphql";


function loadSchemaFile(): string {
  const content = fs.readFileSync("./schema.gql", "utf8");
  return content;
}

const schemaString = loadSchemaFile();
const schema = buildSchema(schemaString);

// The root provides a resolver function for each API endpoint
const root = {};

const getAppServer = () => {
  const app = express();
  app.use(
    "/graphql",
    graphqlHTTP({
      schema: schema,
      graphiql: true,
      rootValue: root,
      validationRules: [],
    })
  );
  return app;
};

if (require.main === module) {
  const app = getAppServer();
  app.listen(4000);
  console.log("Running a GraphQL API server at http://localhost:4000/graphql");
}

index.ts

type Query 

schema.gql

What to add

diff --git a/index.ts b/index.ts
index aeec696..efb025c 100644
--- a/index.ts
+++ b/index.ts
@@ -1,10 +1,8 @@
 import express from "express";
 import fs from "fs";
 import { graphqlHTTP } from "express-graphql";
-import {
-  buildSchema,
-} from "graphql";
-
+import { buildSchema } from "graphql";
+import GraphQLJSON from "graphql-type-json";
 
 function loadSchemaFile(): string {
   const content = fs.readFileSync("./schema.gql", "utf8");
@@ -15,7 +13,15 @@ const schemaString = loadSchemaFile();
 const schema = buildSchema(schemaString);
 
 // The root provides a resolver function for each API endpoint
-const root = {};
+const root = {
+  JSON: GraphQLJSON,
+  translations: () => {
+    return {
+      en: "Hello World",
+      fr: "Bonjour le monde",
+    };
+  },
+};
 
 const getAppServer = () => {
   const app = express();

index.ts

diff --git a/schema.gql b/schema.gql
index 23d124d..0f08403 100644
--- a/schema.gql
+++ b/schema.gql
@@ -1 +1,5 @@
-type Query 
\ No newline at end of file
+type Query {
+  translations: JSON
+}
+
+scalar JSON

schema.gql

Very fast and simple. How many JSON fields do you have in your schema?

You can subscribe on my newsletters

Let's see if we can become internet friends.

Check also related posts

Troy Köhler

TwitterYouTubeInstagramLinkedin