How Schema Validation Works for guidelines.json in JetBrains/go-modern-guidelines

The schema.Parse function performs a single-pass, deterministic 13-step validation pipeline that checks everything from JSON syntax and ID uniqueness to Go version ordering and example snippet completeness, failing fast with descriptive errors on any violation.

The JetBrains/go-modern-guidelines repository maintains its collection of modern Go best practices in a structured JSON file. To ensure data integrity before the tool consumes these rules, the codebase implements rigorous schema validation in internal/guidelines/schema/schema.go that checks semantic constraints beyond simple type matching.

The Entry Point: schema.Parse

When the tool initializes, the loader in internal/guidelines/guidelines.go reads internal/guidelines/guidelines.json and passes the raw bytes to schema.Parse. This function acts as a strict gatekeeper: it either returns a fully-validated slice of guidelines or an error that pinpoints exactly which constraint failed.

The validation is deterministic and exhaustive, iterating through the collection once while maintaining a seenIDs map to detect duplicates. According to the source code, if any check fails, the function immediately returns a wrapped error that aborts program startup, ensuring only valid data reaches the analysis engine.

The 13-Step Validation Pipeline

The Parse function enforces semantic correctness through thirteen distinct checks, organized here by category:

Structural Integrity

First, the validator ensures the file is parseable and non-trivial:

  • JSON syntax — The data must unmarshal cleanly into a []Guideline struct using json.Unmarshal (lines 30-34). Failures surface as “parse guidelines JSON” errors.
  • Non-empty collection — The guidelines slice must contain at least one entry (lines 35-37), preventing empty configurations with the error “guidelines are empty”.

Identifier Constraints

Each guideline requires a unique, well-formed ID:

  • ID format — The validID helper (lines 91-100) scans each rune to enforce that id contains only lowercase letters, digits, or underscores.
  • Duplicate detection — A seenIDs map tracks encountered identifiers (lines 39-47). If a duplicate appears, the validator returns “guideline id … is duplicated”.

Version Control Rules

The validator ensures version information follows Go’s release conventions and logical ordering:

  • Version format — The since_version field must match the major.minor pattern (e.g., “1.27”) validated by goversion.IsMajorMinor (lines 49-52).
  • Ordering constraint — Guidelines must be sorted newest-first (highest version first). The code compares each entry with the previous using goversion.Compare (lines 52-60), returning an error if the sequence is out of order.

Semantic Requirements

Four checks enforce that each guideline contains complete metadata:

  • Modernizer flag — The modernizer field cannot be omitted or nil (lines 61-64). The error “guideline … has no modernizer flag” ensures every rule identifies its corresponding modernization tool.
  • Category presence — The category string must be non-empty (lines 64-66), triggering “guideline … has no category” if missing.
  • Impact enumeration — Impact levels are restricted to Critical, High, Medium, or Low via the validImpact switch statement (lines 103-110).
  • Content completeness — Both the guideline and details fields must contain substantive text. The validator uses strings.TrimSpace to reject blank or whitespace-only strings (lines 70-75), returning errors for missing guideline text or details.

Example Integrity

Finally, the validator ensures educational value through code examples:

  • Example presence — Each guideline must provide at least one example in its Examples array (lines 76-78), or the error “guideline … has no examples” is raised.
  • Snippet completeness — Every example must contain non-empty before and after code blocks (lines 79-86). The validator concatenates and trims the snippet slices, returning specific errors if either side is empty.

Loading Guidelines in Practice

To load and validate the guidelines in your own code, use the schema package:

package main

import (
	"fmt"
	"os"

	"github.com/JetBrains/go-modern-guidelines/internal/guidelines/schema"
)

func main() {
	data, err := os.ReadFile("internal/guidelines/guidelines.json")
	if err != nil {
		panic(err)
	}
	guidelines, err := schema.Parse(data)
	if err != nil {
		// Validation failed – the error explains the exact problem.
		fmt.Printf("Invalid guidelines.json: %v\n", err)
		os.Exit(1)
	}
	fmt.Printf("Loaded %d guidelines successfully.\n", len(guidelines))
}

Running the program prints:


Loaded 150 guidelines successfully.

If validation fails, the output identifies the specific violation:


Invalid guidelines.json: guideline "strings_cut" has empty after snippet

Once parsed, the data is safe to iterate without additional checks:

for _, g := range guidelines {
    fmt.Printf("- %s (%s) – %s\n", g.ID, g.SinceVersion, g.Impact)
}

Summary

  • schema.Parse in internal/guidelines/schema/schema.go serves as the single validation entry point, called by internal/guidelines/guidelines.go.
  • The validator performs thirteen distinct checks covering syntax, ID uniqueness, version formatting (major.minor), ordering (newest-first), required fields, enum values, and example completeness.
  • Validation is fail-fast: the first error encountered aborts loading, preventing the tool from running with corrupt data.
  • IDs must be lowercase alphanumeric with underscores; impact must be Critical, High, Medium, or Low; versions must follow Go’s major.minor pattern.
  • Every guideline must include at least one example with non-empty before and after code snippets.

Frequently Asked Questions

What happens if guidelines.json contains duplicate IDs?

The seenIDs map in schema.Parse detects duplicates during the single-pass iteration (lines 39-47). When a duplicate is found, the function immediately returns an error formatted as “guideline id … is duplicated”, causing the program to exit before processing any guidelines.

Why must guidelines be sorted newest-first in the JSON?

The validator enforces descending version order using goversion.Compare (lines 52-60) to ensure the tool presents the most recent Go features first during modernization checks. If an entry has a lower version than its predecessor, the parser returns an ordering error.

What are the valid values for the impact field?

The validImpact function (lines 103-110) restricts the impact field to exactly four string values: Critical, High, Medium, or Low. Any other value causes validation to fail with an impact-specific error.

How does the validator check example code snippets?

For each example, the validator concatenates the before and after string slices, trims whitespace, and checks for empty results (lines 79-86). If either side is blank after trimming, it returns specific errors distinguishing between missing before snippets, missing after snippets, or completely empty examples.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →