How to enable JSON or YAML validation with JSON Schemas in IntelliJ



Last modified on January 3, 2026

This is another article about plugin development for IntelliJ-based IDEs. In this article, I am describing how to implement some support for JSON or YAML files using a JSON Schema. While the JSON support is expected, the YAML support is a bit more surprising. It is possible because JSON and YAML are very similar formats, YAML 1.2 even being a superset of JSON.

I recently implemented that trick in my plugin FHIR® and SUSHI Support to provide a better experience while working with a specific YAML file (the sushi-config.yaml file). I discovered that neat feature in the YAML documentation, but I had to use the IntelliJ Platform Explorer to discover how a plugin could register a new JSON Schema in the IDE. That topic isn't covered by the IntelliJ Platform SDK Documentation documentation, so I am sharing my findings here.

Supported features#

The features automatically provided by the IntelliJ SDK (at the time of writing) when a JSON Schema is enabled are:

Notably, the following features are NOT supported:

There are many other features of JSON Schema that I did not test, so this list is not exhaustive. Overall, the support is good enough to provide a nice assistance to the user, because it's tightly integrated into the IDE. But if you're looking to perform a full validation of files against a JSON Schema, you may want to consider alternative implementations, because of the missing features listed above.

For my plugin, I wanted to provide a better experience when editing the sushi-config.yaml file, not a full validation, so I'm satisfied with the current state of the support. Let's proceed to the implementation!

The implementation#

Let's go into the implementation details. For these examples, I am using the IntelliJ Platform Plugin Template, but your plugin structure may differ slightly.

The implementation is straightforward, and requires three main steps: a JSON Schema, a provider class with its factory, and a registration in the plugin configuration file.

A JSON Schema#

First, we need a JSON Schema to work with. Creating a JSON Schema is out of the scope of this article, but there are many resources online to help with that, and I found it rather easy to write one manually. I'm also sure there are good tools with graphical interfaces to help visualizing and editing the schemas.

Once you have your schema, you need to add it to your plugin resources. In the plugin template structure, that would be under my-plugin/src/main/resources/. For this example, I simply named my schema file schema.json.

A provider#

Next, we create a new class extending JsonSchemaFileProvider to provide our schema to the IDE. But that interface we are extending is not part of the standard IntelliJ API, but is an additional plugin that we need to declare as a build dependency in the Gradle configuration (despite its name, it's not a module but a plugin):

properties gradle.properties
1
platformBundledPlugins = com.intellij.modules.json

Or with the regular gradle.build.kts file (with the IntelliJ Platform Gradle Plugin 2.0+):

kotlin gradle.build.kts
1
2
3
4
5
6
7
dependencies {
    // …
    // IntelliJ Platform Gradle Plugin Dependencies Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html
    intellijPlatform {
        bundledPlugin("com.intellij.modules.json")
    }
}

Now, we can implement our provider:

kotlin MyJsonSchemaProvider.kt
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package org.jetbrains.plugins.template

import com.intellij.openapi.vfs.VirtualFile
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider
import com.jetbrains.jsonSchema.extension.JsonSchemaProviderFactory
import com.jetbrains.jsonSchema.extension.SchemaType
import com.jetbrains.jsonSchema.impl.JsonSchemaVersion
import org.jetbrains.annotations.Nls

class MyJsonSchemaProvider : JsonSchemaFileProvider {
    override fun isAvailable(file: VirtualFile): Boolean = file.name == "sushi-config.yaml"
    override fun getName(): @Nls String = "sushi-config.yaml schema"
    override fun getSchemaType(): SchemaType = SchemaType.embeddedSchema
    override fun getSchemaVersion(): JsonSchemaVersion = JsonSchemaVersion.SCHEMA_2020_12
    override fun getSchemaFile(): VirtualFile? =
        JsonSchemaProviderFactory.getResourceFile(javaClass, "/schema.json")
}

The following methods are implemented:

The next step is to create a factory for our provider. This is really straightforward:

kotlin MyJsonSchemaProviderFactory.kt
1
2
3
4
5
6
7
8
9
package org.jetbrains.plugins.template

import com.intellij.openapi.project.Project
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider
import com.jetbrains.jsonSchema.extension.JsonSchemaProviderFactory

class MyJsonSchemaProviderFactory : JsonSchemaProviderFactory {
    override fun getProviders(project: Project): List<JsonSchemaFileProvider> = listOf(MyJsonSchemaProvider())
}

A registration#

The last step is to register our factory in the plugin configuration file, and declare a runtime dependency on the JSON plugin. Since it's a plugin, it could be unavailable at runtime, and IntelliJ offers us two choices to deal with that:

  1. refuse to load our plugin, because we require the JSON plugin;
  2. continue to load our plugin, but disable that feature.

Which solution to implement depends on the context of the developed plugin. At the time of writing, I am unable to disable the JSON plugin in my IDEs, so I am unsure if that situation is really possible, but I choose the second solution for my plugin – better safe than sorry. The first solution is simply implemented by declaring a mandatory dependency on the JSON plugin:

xml plugin.xml (mandatory dependency)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
<idea-plugin>
    <id>org.jetbrains.plugins.template</id>
    <name>IntelliJ Platform Plugin Template</name>
    <depends>com.intellij.modules.platform</depends>
    <depends>com.intellij.modules.json</depends>
    <extensions defaultExtensionNs="com.intellij">
        <!-- Other extensions… -->
    </extensions>
    <extensions defaultExtensionNs="JavaScript.JsonSchema">
        <ProviderFactory implementation="org.jetbrains.plugins.template.MyJsonSchemaProviderFactory"/>
    </extensions>
</idea-plugin>

The second solution is implemented by declaring an optional dependency on the JSON plugin, and creating a second plugin configuration file that is only loaded when the JSON plugin is available. You can name it as you want.

xml plugin.xml (optional dependency)
1
2
3
4
5
6
<idea-plugin>
    <id>org.jetbrains.plugins.template</id>
    <name>IntelliJ Platform Plugin Template</name>
    <depends>com.intellij.modules.platform</depends>
    <depends optional="true" config-file="plugin_with_json.xml">com.intellij.modules.json</depends>
</idea-plugin>
xml plugin_with_json.xml (optional dependency)
1
2
3
4
5
<idea-plugin>
    <extensions defaultExtensionNs="JavaScript.JsonSchema">
        <ProviderFactory implementation="org.jetbrains.plugins.template.MyJsonSchemaProviderFactory"/>
    </extensions>
</idea-plugin>

The result#

Here is the result of the implementation in my plugin, when editing a sushi-config.yaml file:

The 'sushi-config.yaml' file opened in the IDE

The ‘sushi-config.yaml’ file opened in the IDE


Autocompletion suggestions based on the JSON Schema

Autocompletion suggestions based on the JSON Schema


An example of validation error

An example of validation error


The description shown for the element 'dependencies'

The description shown for the element ‘dependencies’