2021-08-12

Using JSON Schema for Visual Studio Code autocompletion

I’ve been working on a few code generations ideas that I have and found the need to create a number of

JSON
and
YAML
configuration files feed into the code generation system.

I’ve built a few small scale versions of this kidn of thing over the years. Typcially when you’re working on a system designed as a set of

Microservice
s, a client-server or 3-tier style application you’ll spend a lot of time creating and maintaining
DTO
s to share data between the different layers of the application or between different services.

This is a very time consuming and error prone process. Every couple of years, I’ll try some of the latest tools that seem to help in this area, and I think you need a few things to be useful for the average programmer.

  • A system that doesn’t require a 4-year degree to pick up
  • An easy, clean, and simple way to define a source of truth for your application models
  • Integration with your code editors and
    IDE
    s

Every couple of years I try out things like the

EMF
and similar systems, or tools like
OAS
(which using
JSON Schema
as a foundation specification). And I’ve also spend some time reading up on the internals of the Visual Studio Code
Language Extentions
.

The four year degree software

I haven’t reviewed

EMF
in a couple of years now (and I’m assuming it’s gotten more polished and easier to use), however it is one of those software that is grand in scope, very academically interesting, and probably would take the same amount of time as getting a 4-year degree to learn and use well.

I recall concepts you have to keep in your head also makes this a bit of an issue to use while you’re trying to think through the design you’re actually getting paid to build.

Easy, clean, and simple way to define your source of truth

Using something like the

is good for editor and
IDE
integration. While I think it’s was easier to understand it again seems like a lot of work for simple tasks.

I think systems like

OAS
is closer to what I’m looking for, however it’s really designed for interface design of a specific type of communication protocol (much like
AsyncAPI
). These aren’t really general enough in my opinion.

Integeration with you code editors and IDEs

The

EMF
has good tooling in the Eclipse
IDE
, and the integration for
OAS
and
AsyncAPI
have some good tooling integration, the support and coverage isn’t very polished yet that I’ve found.

A good start

I used the following articles as a getting started guide for this work:

While this isn’t a a real code generation tool. I found something related to the IDE integration using

JSON Schema
(The foundation that
OAS
and
AsyncAPI
are built on), and provides a somewhat easy usage method to quickly specification editor integration, and share with team members.

For this site I’ve built a simple code generation tool that uses the a

YAML
(or
JSON
) data file defined using
JSON Schema
to generate
Svelte
components that implements the pop-up controls used on this page (and the other pages of this site).

First I started with a

TS
interface which looks like this:

export interface Data {
    title: string
    abbr?: string
    desc?: string
    refs?: Ref[]
}

export interface Ref {
    url: string
    title?: string
    desc?: string
}

Which is a relativly simple interface (and simplied for the real interfaced use to generated the pop-ups on this site).

The interface has the following:

  • title: displayed inline with the page text and displayed on the title position of the
    Standard Card
    displayed in the pop-up.
  • abbr: if provided displayed inline with the page text (instead of the title) and as a parenthetical on the title position of the
    Standard Card
    displayed in the pop-up.
  • desc if provided is displayed in the main content position of the
    Standard Card
    displayed in the pop-up.
  • refs[]: if provided is is displayed as a list in the main content position of the
    Standard Card
    displayed in the pop-up.

I wanted to be able to create a data file in

YAML
which looks like the following:

ide:
    title: <b>I</b>ntegrated  <b>D</b>evelopment <b>E</b>nvironment
    abbr:
        - visual studio code
    desc: A software application that provides comprehensive facilities to computer programmers for software development.
    refs:
        -   title: Wikipedia
            url: https://en.wikipedia.org/wiki/Integrated_development_environment

which will generate a

Svelte
component like:

<script lang="ts">
    import type {Data} from '$lib/popover/Data'
    import DataCard from '$lib/popover/Data.svelte'

    const data:Data = {
    "title": "<b>I</b>ntegrated  <b>D</b>evelopment <b>E</b>nvironment",
    "abbr": "IDE",
    "desc": "A software application that provides comprehensive facilities to computer programmers for software development.",
    "refs": [
        {
            "title": "Wikipedia",
            "url": "https://en.wikipedia.org/wiki/Integrated_development_environment"
        }
    ]
}
</script>

<DataCard {data} />

and a

TS
index.ts file which exports this component in a simple way:

...
import ide from './Ide.svelte'
...
export const IDE = ide

which allows me to import the pop-up like:

<script lang="ts">
    import { IDE } from '$lib/ref/tooltip';
</script>


This is a example of the <IDE /> Svelte based pop-up.

While this artice isn’t about the component itself, to make something like this useful you need to be able to edit the input data file easily to add items while you’re writing and avoid to much of a context switch. If you’re constantly trying to lookup the interfaces and reviewing the code to recall which parameters are available the usage of the system will not be fun.

For the above, I created the following

JSON Schema
file (and saved it at <WORKSPACE_DIR>/.vscode/json-schema.json):

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "title": "JSON Schema for data generator",
    "type": "object",
    "patternProperties": {
        "[a-zA-Z0-9_]": {
            "required": ["title"],
            "properties": {
                "title": {
                    "type": "string"
                },
                "abbr": {
                    "type": "string"
                },
                "desc": {
                    "type": "string"
                },
                "refs": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/refs"
                    }
                },                
            }
        }
    },
    "definitions": {
        "refs": {
            "type": "object",
            "required": ["url"],
            "properties": {
                "url": {
                    "type": "string"
                },
                "title": {
                    "type": "string"
                },
                "desc": {
                    "type": "string"
                }
            }
        },        
    }
}

and added the following section to the

vscode Settings
file in the workspace, <WORKSPACE_DIR>/.vscode/settings.json:

{
    "yaml.schemas": {
        "./.vscode/json-schema.json": [
            "**/*.data.yaml",
            "*.data.yaml",
            "/gen/*"
        ]
    },
    "json.schemas": [
        {
            "fileMatch": ["*.data.yaml"],
            "url": "./.vscode/json-schema.json"
        }
    ]
}
© Bounded Infinity 2025