Need help with your JSON?
Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool
Implementing JSON Formatter Plugins for JetBrains IDEs
JetBrains IDEs already ship with a capable formatter for standard JSON. A custom plugin makes sense when you need more than the built-in JSON code style settings can provide: support for a JSON-like language, a canonical house style, schema-aware formatting, or delegation to an external formatter that already exists in your toolchain.
The key decision is choosing the right IntelliJ Platform integration point. In the current JetBrains SDK docs, built-in formatter logic lives behind com.intellij.lang.formatter, external formatter integrations use com.intellij.formattingService, and structural edits that go beyond whitespace belong in a PostFormatProcessor.
Choose the Right Formatter Strategy
Before you write any plugin code, decide which of these paths matches your actual problem:
- Use the built-in JSON formatter if you only need different indentation, wrapping, or spacing defaults for plain
.jsonfiles. - Use a custom language formatter if your plugin owns a JSON dialect or JSON-like file type and the IDE should compute spacing, indents, wraps, and alignment directly from PSI.
- Use an external formatting service if your formatter already exists as a CLI or another executable and your plugin should delegate instead of recreating every rule in
Blocklogic. - Use post-format processing if you need token or syntax changes after formatting, such as adding commas, rewriting quotes, or inserting boilerplate.
For most "JSON formatter plugin" use cases, the real choice is between a custom FormattingModelBuilder and an AsyncDocumentFormattingService.
What a Current JetBrains Formatter Plugin Needs
If you are formatting a custom JSON dialect inside the IDE, these are the parts that matter today:
- Parser definition: your formatter only works well if the PSI tree cleanly represents objects, arrays, properties, literals, commas, colons, and any extensions such as comments or trailing commas.
FormattingModelBuilder: this builds the root formatting model from the currentFormattingContext.AbstractBlock-based block tree: blocks usually mirror PSI nodes and decide indent, spacing, wrapping, and alignment.SpacingBuilder: this is still the simplest way to express JSON punctuation rules such as no space before a colon and one space after it.getChildAttributes()andisIncomplete(): these are easy to skip, but they drive how the IDE indents new lines when users press Enter in partially typed JSON.- Code style settings providers: expose only the toggles users actually expect, such as indent size, spaces after
:, spaces within braces, wrapping of arrays, or alignment behavior.
One current SDK caveat matters a lot: JetBrains documents that the formatter primarily controls whitespace between adjacent leaf blocks. If your plugin must sort keys, insert missing syntax, or rewrite tokens, do that in a post-processor or an external formatter instead of forcing it into spacing rules.
Minimal Registration and Builder Example
For a custom JSON-like language, the current formatter registration is centered on com.intellij.lang.formatter. The important detail is that the formatter extension now uses the language attribute:
plugin.xml (formatter-related parts)
<extensions defaultExtensionNs="com.intellij">
<lang.parserDefinition
language="Jsonish"
implementationClass="com.example.jsonish.JsonishParserDefinition" />
<lang.formatter
language="Jsonish"
implementationClass="com.example.jsonish.JsonishFormattingModelBuilder" />
<codeStyleSettingsProvider
implementation="com.example.jsonish.JsonishCodeStyleSettingsProvider" />
<langCodeStyleSettingsProvider
implementation="com.example.jsonish.JsonishLanguageCodeStyleSettingsProvider" />
<fileTypeIndentOptionsProvider
implementation="com.example.jsonish.JsonishIndentOptionsProvider" />
</extensions>A minimal builder should create a PSI-based formatting model, not a fully custom formatting engine:
Kotlin example
final class JsonishFormattingModelBuilder : FormattingModelBuilder {
override fun createModel(formattingContext: FormattingContext): FormattingModel {
val settings = formattingContext.codeStyleSettings
val rootBlock = JsonishBlock(
formattingContext.node,
Wrap.createWrap(WrapType.NONE, false),
Alignment.createAlignment(),
createSpacingBuilder(settings)
)
return FormattingModelProvider.createFormattingModelForPsiFile(
formattingContext.containingFile,
rootBlock,
settings
)
}
private fun createSpacingBuilder(settings: CodeStyleSettings) =
SpacingBuilder(settings, JsonishLanguage)
.before(JsonishTypes.COLON).none()
.after(JsonishTypes.COLON).spaceIf(true)
.before(JsonishTypes.COMMA).none()
.after(JsonishTypes.COMMA).spaceIf(true)
}The JsonishBlock class should usually extend AbstractBlock, recursively build child blocks for non-whitespace nodes, and compute indentation from container types such as objects and arrays.
Code Style Settings Users Actually Need
A formatter plugin feels incomplete if users cannot discover or change its behavior in Settings. The current JetBrains tutorial flow still uses three pieces:
CustomCodeStyleSettingsfor your language-specific options.CodeStyleSettingsProviderto create the settings object and the settings page.LanguageCodeStyleSettingsProviderto expose standard spacing, blank-line, and wrapping controls plus a code sample.
If your JSON dialect should default to two-space indents, tabs disabled, or another nonstandard indent behavior, add a FileTypeIndentOptionsProvider too. That keeps your defaults explicit instead of depending on whatever the user last configured globally.
Keep the setting surface small. JSON users typically expect predictable indentation, colon and comma spacing, wrapping rules for long arrays and objects, and maybe whether properties should align. Anything more complex quickly turns into noise unless your dialect has real extra syntax.
Testing, Debugging, and 2026 Compatibility Notes
Current JetBrains tutorials still run formatter plugins with the Gradle runIde task. In the IDE development instance, inspect your tree with the PsiViewer plugin or the built-in PSI viewer before you debug spacing bugs at the block layer.
- Test nested objects and arrays with both short and long lines so wrapping decisions are obvious.
- Test incomplete JSON, because Enter handling depends on
getChildAttributes()andisIncomplete(). - Test any JSON extensions explicitly, such as comments, unquoted keys, trailing commas, or multiline string forms.
- Test large files, because formatting runs often and expensive PSI walks are noticeable.
As of early 2026, JetBrains' public SDK docs still describe lang.formatter for in-IDE formatting, AsyncDocumentFormattingService for external formatters, and code style settings based on CustomCodeStyleSettings, CodeStyleSettingsProvider, and LanguageCodeStyleSettingsProvider. That is the baseline to target unless you have a strong reason to depend on newer internal APIs.
Useful current references are the JetBrains Code Formatter docs, the formatter tutorial step, the code style settings guide, and the parser definition guide.
Common Mistakes to Avoid
- Do not wire a primary formatter through
LanguageInjector. That is the wrong API for this job. - Do not assume a formatter can handle semantic rewrites. Whitespace formatting and document transformation are separate concerns in the platform.
- Do not copy the built-in JSON formatter unless you truly need a new language. If your files are standard JSON, a settings tweak is cheaper to build and easier to maintain.
- Do not ship an external formatter integration without clear failure handling when the binary is missing, slow, or returns invalid output.
Bottom Line
The modern way to build a JSON formatter plugin for JetBrains IDEs is straightforward once you pick the right extension point. Use FormattingModelBuilder and an AbstractBlock tree for a custom JSON language, use AsyncDocumentFormattingService when an external formatter should stay the source of truth, and keep structural rewrites out of spacing rules. That gives search visitors a realistic implementation path instead of an abstract tour of old APIs.
Need help with your JSON?
Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool