CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-fge--json-schema-validator

A comprehensive Java implementation of the JSON Schema validation specification supporting both draft v4 and v3 with complete validation capabilities and extensibility.

Pending
Overview
Eval results
Files

syntax-validation.mddocs/

Syntax Validation

Dedicated functionality for validating JSON Schema syntax without performing instance validation. The syntax validator ensures that schemas conform to the JSON Schema specification structure and rules before they are used for instance validation.

Capabilities

SyntaxValidator

Standalone validator for checking JSON Schema syntax and structure.

/**
 * Validator for JSON Schema syntax without instance validation
 */
public final class SyntaxValidator {
    /**
     * Check if schema has valid syntax
     * @param schema JsonNode containing the JSON schema to validate
     * @return true if schema syntax is valid, false otherwise
     */
    public boolean schemaIsValid(JsonNode schema);
    
    /**
     * Validate schema syntax and return detailed report
     * @param schema JsonNode containing the JSON schema to validate
     * @return ProcessingReport with validation results and error details
     * @throws ProcessingException if syntax validation processing fails
     */
    public ProcessingReport validateSchema(JsonNode schema) throws ProcessingException;
    
    /**
     * Get underlying processor for advanced usage
     * @return Processor for schema tree validation
     */
    public Processor<ValueHolder<SchemaTree>, ValueHolder<SchemaTree>> getProcessor();
}

Usage Examples:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.fge.jsonschema.processors.syntax.SyntaxValidator;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.core.report.ProcessingReport;

// Get syntax validator from factory
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
SyntaxValidator syntaxValidator = factory.getSyntaxValidator();

// Simple boolean validation
ObjectMapper mapper = new ObjectMapper();
JsonNode validSchema = mapper.readTree("{\n" +
    "  \"type\": \"object\",\n" +
    "  \"properties\": {\n" +
    "    \"name\": { \"type\": \"string\" },\n" +
    "    \"age\": { \"type\": \"integer\", \"minimum\": 0 }\n" +
    "  },\n" +
    "  \"required\": [\"name\"]\n" +
    "}");

boolean isValid = syntaxValidator.schemaIsValid(validSchema);
System.out.println("Schema is valid: " + isValid); // true

// Detailed validation report
ProcessingReport report = syntaxValidator.validateSchema(validSchema);
if (report.isSuccess()) {
    System.out.println("Schema syntax is correct");
} else {
    System.out.println("Schema syntax errors:");
    for (ProcessingMessage message : report) {
        System.out.println("  " + message.getMessage());
    }
}

// Validate invalid schema
JsonNode invalidSchema = mapper.readTree("{\n" +
    "  \"type\": \"object\",\n" +
    "  \"properties\": {\n" +
    "    \"age\": { \"type\": \"integer\", \"minimum\": \"not-a-number\" }\n" +
    "  }\n" +
    "}");

ProcessingReport invalidReport = syntaxValidator.validateSchema(invalidSchema);
if (!invalidReport.isSuccess()) {
    System.out.println("Syntax errors found:");
    for (ProcessingMessage message : invalidReport) {
        System.out.println("  Path: " + message.asJson().get("instance").get("pointer"));
        System.out.println("  Error: " + message.getMessage());
    }
}

Schema Syntax Requirements

Draft v4 Schema Structure

// Valid Draft v4 schema structure
{
  "$schema": "http://json-schema.org/draft-04/schema#",  // Optional
  "type": "object",                                     // Root type
  "properties": {                                       // Object properties
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name"],                                 // Required properties
  "additionalProperties": false                        // Additional property control
}

Draft v3 Schema Structure

// Valid Draft v3 schema structure  
{
  "$schema": "http://json-schema.org/draft-03/schema#",  // Optional
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer", "minimum": 0 }
  },
  "required": ["name"],                                  // Different required syntax
  "additionalProperties": false
}

Common Syntax Validation Scenarios

Example 1: Pre-validation Schema Check

/**
 * Validate schema syntax before using it for instance validation
 */
public JsonSchema createSchemaWithValidation(JsonNode schemaNode) throws ProcessingException {
    JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
    SyntaxValidator syntaxValidator = factory.getSyntaxValidator();
    
    // Check syntax first
    ProcessingReport syntaxReport = syntaxValidator.validateSchema(schemaNode);
    if (!syntaxReport.isSuccess()) {
        StringBuilder errors = new StringBuilder("Schema syntax errors:\n");
        for (ProcessingMessage message : syntaxReport) {
            errors.append("  ").append(message.getMessage()).append("\n");
        }
        throw new ProcessingException(errors.toString());
    }
    
    // Safe to create schema instance
    return factory.getJsonSchema(schemaNode);
}

Example 2: Schema Validation Service

/**
 * Service for validating multiple schemas
 */
public class SchemaValidationService {
    private final SyntaxValidator syntaxValidator;
    
    public SchemaValidationService() {
        this.syntaxValidator = JsonSchemaFactory.byDefault().getSyntaxValidator();
    }
    
    public ValidationResult validateSchemas(List<JsonNode> schemas) {
        List<String> errors = new ArrayList<>();
        List<JsonNode> validSchemas = new ArrayList<>();
        
        for (int i = 0; i < schemas.size(); i++) {
            JsonNode schema = schemas.get(i);
            ProcessingReport report = syntaxValidator.validateSchema(schema);
            
            if (report.isSuccess()) {
                validSchemas.add(schema);
            } else {
                StringBuilder schemaErrors = new StringBuilder();
                schemaErrors.append("Schema ").append(i).append(" errors:\n");
                for (ProcessingMessage message : report) {
                    schemaErrors.append("  ").append(message.getMessage()).append("\n");
                }
                errors.add(schemaErrors.toString());
            }
        }
        
        return new ValidationResult(validSchemas, errors);
    }
    
    public boolean isValidSchema(JsonNode schema) {
        return syntaxValidator.schemaIsValid(schema);
    }
}

public class ValidationResult {
    private final List<JsonNode> validSchemas;
    private final List<String> errors;
    
    public ValidationResult(List<JsonNode> validSchemas, List<String> errors) {
        this.validSchemas = validSchemas;
        this.errors = errors;
    }
    
    public boolean hasErrors() {
        return !errors.isEmpty();
    }
    
    public List<JsonNode> getValidSchemas() {
        return validSchemas;
    }
    
    public List<String> getErrors() {
        return errors;
    }
}

Example 3: Schema Development Tool

/**
 * Development utility for interactive schema validation
 */
public class SchemaDebugger {
    private final SyntaxValidator syntaxValidator;
    private final ObjectMapper mapper;
    
    public SchemaDebugger() {
        this.syntaxValidator = JsonSchemaFactory.byDefault().getSyntaxValidator();
        this.mapper = new ObjectMapper();
    }
    
    public void debugSchema(String schemaJson) {
        try {
            JsonNode schema = mapper.readTree(schemaJson);
            System.out.println("=== Schema Syntax Validation ===");
            System.out.println("Schema:");
            System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
            System.out.println();
            
            ProcessingReport report = syntaxValidator.validateSchema(schema);
            
            if (report.isSuccess()) {
                System.out.println("✓ Schema syntax is valid");
                System.out.println("Schema version: " + detectSchemaVersion(schema));
            } else {
                System.out.println("✗ Schema syntax errors found:");
                for (ProcessingMessage message : report) {
                    JsonNode messageJson = message.asJson();
                    String pointer = messageJson.get("instance").get("pointer").asText();
                    String error = message.getMessage();
                    
                    System.out.println("  Location: " + (pointer.isEmpty() ? "/" : pointer));
                    System.out.println("  Error: " + error);
                    System.out.println();
                }
            }
            
        } catch (Exception e) {
            System.out.println("✗ Invalid JSON: " + e.getMessage());
        }
    }
    
    private String detectSchemaVersion(JsonNode schema) {
        JsonNode schemaUri = schema.get("$schema");
        if (schemaUri != null) {
            return schemaUri.asText();
        }
        return "Draft v4 (default)";
    }
    
    public static void main(String[] args) {
        SchemaDebugger debugger = new SchemaDebugger();
        
        // Test valid schema
        String validSchema = "{\n" +
            "  \"type\": \"object\",\n" +
            "  \"properties\": {\n" +
            "    \"name\": { \"type\": \"string\" }\n" +
            "  }\n" +
            "}";
        debugger.debugSchema(validSchema);
        
        // Test invalid schema
        String invalidSchema = "{\n" +
            "  \"type\": \"object\",\n" +
            "  \"properties\": {\n" +
            "    \"age\": { \"type\": \"integer\", \"minimum\": \"invalid\" }\n" +
            "  }\n" +
            "}";
        debugger.debugSchema(invalidSchema);
    }
}

Syntax Validation Rules

Type Validation Rules

  • type must be a string or array of strings
  • Valid types: "null", "boolean", "object", "array", "number", "integer", "string"
  • Array types must contain unique values

Numeric Constraint Rules

  • minimum, maximum must be numbers
  • exclusiveMinimum, exclusiveMaximum must be booleans (Draft v4) or numbers (Draft v6+)
  • multipleOf must be a positive number

String Constraint Rules

  • minLength, maxLength must be non-negative integers
  • pattern must be a valid regular expression string

Array Constraint Rules

  • minItems, maxItems must be non-negative integers
  • items must be an object or array of objects
  • additionalItems must be boolean or object

Object Constraint Rules

  • properties must be an object with schema values
  • patternProperties must be an object with regex keys and schema values
  • additionalProperties must be boolean or object
  • required must be array of strings (Draft v4) or boolean (Draft v3)
  • minProperties, maxProperties must be non-negative integers

Integration with Validation

/**
 * Complete validation pipeline with syntax checking
 */
public class CompleteValidationPipeline {
    private final JsonSchemaFactory factory;
    private final SyntaxValidator syntaxValidator;
    
    public CompleteValidationPipeline() {
        this.factory = JsonSchemaFactory.byDefault();
        this.syntaxValidator = factory.getSyntaxValidator();
    }
    
    public ProcessingReport validateWithSyntaxCheck(JsonNode schema, JsonNode instance) throws ProcessingException {
        // Step 1: Validate schema syntax
        ProcessingReport syntaxReport = syntaxValidator.validateSchema(schema);
        if (!syntaxReport.isSuccess()) {
            return syntaxReport; // Return syntax errors
        }
        
        // Step 2: Create schema and validate instance
        JsonSchema jsonSchema = factory.getJsonSchema(schema);
        return jsonSchema.validate(instance);
    }
    
    public ValidationResult completeValidation(JsonNode schema, JsonNode instance) {
        try {
            ProcessingReport report = validateWithSyntaxCheck(schema, instance);
            return new ValidationResult(report.isSuccess(), report);
        } catch (ProcessingException e) {
            return new ValidationResult(false, null, e.getMessage());
        }
    }
}

Best Practices

  1. Early Validation: Always validate schema syntax before instance validation
  2. Error Reporting: Use detailed reports to provide clear feedback on syntax issues
  3. Development Workflow: Integrate syntax validation into schema development tools
  4. Performance: Cache syntax validation results for frequently used schemas
  5. Version Awareness: Be explicit about JSON Schema version compatibility
  6. Testing: Include syntax validation in your schema test suites

Install with Tessl CLI

npx tessl i tessl/maven-com-github-fge--json-schema-validator

docs

basic-validation.md

cli.md

configuration.md

extensions.md

format-validation.md

index.md

syntax-validation.md

tile.json