0
# Syntax Validation
1
2
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.
3
4
## Capabilities
5
6
### SyntaxValidator
7
8
Standalone validator for checking JSON Schema syntax and structure.
9
10
```java { .api }
11
/**
12
* Validator for JSON Schema syntax without instance validation
13
*/
14
public final class SyntaxValidator {
15
/**
16
* Check if schema has valid syntax
17
* @param schema JsonNode containing the JSON schema to validate
18
* @return true if schema syntax is valid, false otherwise
19
*/
20
public boolean schemaIsValid(JsonNode schema);
21
22
/**
23
* Validate schema syntax and return detailed report
24
* @param schema JsonNode containing the JSON schema to validate
25
* @return ProcessingReport with validation results and error details
26
* @throws ProcessingException if syntax validation processing fails
27
*/
28
public ProcessingReport validateSchema(JsonNode schema) throws ProcessingException;
29
30
/**
31
* Get underlying processor for advanced usage
32
* @return Processor for schema tree validation
33
*/
34
public Processor<ValueHolder<SchemaTree>, ValueHolder<SchemaTree>> getProcessor();
35
}
36
```
37
38
**Usage Examples:**
39
40
```java
41
import com.fasterxml.jackson.databind.JsonNode;
42
import com.fasterxml.jackson.databind.ObjectMapper;
43
import com.github.fge.jsonschema.processors.syntax.SyntaxValidator;
44
import com.github.fge.jsonschema.main.JsonSchemaFactory;
45
import com.github.fge.jsonschema.core.report.ProcessingReport;
46
47
// Get syntax validator from factory
48
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
49
SyntaxValidator syntaxValidator = factory.getSyntaxValidator();
50
51
// Simple boolean validation
52
ObjectMapper mapper = new ObjectMapper();
53
JsonNode validSchema = mapper.readTree("{\n" +
54
" \"type\": \"object\",\n" +
55
" \"properties\": {\n" +
56
" \"name\": { \"type\": \"string\" },\n" +
57
" \"age\": { \"type\": \"integer\", \"minimum\": 0 }\n" +
58
" },\n" +
59
" \"required\": [\"name\"]\n" +
60
"}");
61
62
boolean isValid = syntaxValidator.schemaIsValid(validSchema);
63
System.out.println("Schema is valid: " + isValid); // true
64
65
// Detailed validation report
66
ProcessingReport report = syntaxValidator.validateSchema(validSchema);
67
if (report.isSuccess()) {
68
System.out.println("Schema syntax is correct");
69
} else {
70
System.out.println("Schema syntax errors:");
71
for (ProcessingMessage message : report) {
72
System.out.println(" " + message.getMessage());
73
}
74
}
75
76
// Validate invalid schema
77
JsonNode invalidSchema = mapper.readTree("{\n" +
78
" \"type\": \"object\",\n" +
79
" \"properties\": {\n" +
80
" \"age\": { \"type\": \"integer\", \"minimum\": \"not-a-number\" }\n" +
81
" }\n" +
82
"}");
83
84
ProcessingReport invalidReport = syntaxValidator.validateSchema(invalidSchema);
85
if (!invalidReport.isSuccess()) {
86
System.out.println("Syntax errors found:");
87
for (ProcessingMessage message : invalidReport) {
88
System.out.println(" Path: " + message.asJson().get("instance").get("pointer"));
89
System.out.println(" Error: " + message.getMessage());
90
}
91
}
92
```
93
94
## Schema Syntax Requirements
95
96
### Draft v4 Schema Structure
97
```java
98
// Valid Draft v4 schema structure
99
{
100
"$schema": "http://json-schema.org/draft-04/schema#", // Optional
101
"type": "object", // Root type
102
"properties": { // Object properties
103
"name": { "type": "string" },
104
"age": { "type": "integer", "minimum": 0 }
105
},
106
"required": ["name"], // Required properties
107
"additionalProperties": false // Additional property control
108
}
109
```
110
111
### Draft v3 Schema Structure
112
```java
113
// Valid Draft v3 schema structure
114
{
115
"$schema": "http://json-schema.org/draft-03/schema#", // Optional
116
"type": "object",
117
"properties": {
118
"name": { "type": "string" },
119
"age": { "type": "integer", "minimum": 0 }
120
},
121
"required": ["name"], // Different required syntax
122
"additionalProperties": false
123
}
124
```
125
126
## Common Syntax Validation Scenarios
127
128
### Example 1: Pre-validation Schema Check
129
```java
130
/**
131
* Validate schema syntax before using it for instance validation
132
*/
133
public JsonSchema createSchemaWithValidation(JsonNode schemaNode) throws ProcessingException {
134
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
135
SyntaxValidator syntaxValidator = factory.getSyntaxValidator();
136
137
// Check syntax first
138
ProcessingReport syntaxReport = syntaxValidator.validateSchema(schemaNode);
139
if (!syntaxReport.isSuccess()) {
140
StringBuilder errors = new StringBuilder("Schema syntax errors:\n");
141
for (ProcessingMessage message : syntaxReport) {
142
errors.append(" ").append(message.getMessage()).append("\n");
143
}
144
throw new ProcessingException(errors.toString());
145
}
146
147
// Safe to create schema instance
148
return factory.getJsonSchema(schemaNode);
149
}
150
```
151
152
### Example 2: Schema Validation Service
153
```java
154
/**
155
* Service for validating multiple schemas
156
*/
157
public class SchemaValidationService {
158
private final SyntaxValidator syntaxValidator;
159
160
public SchemaValidationService() {
161
this.syntaxValidator = JsonSchemaFactory.byDefault().getSyntaxValidator();
162
}
163
164
public ValidationResult validateSchemas(List<JsonNode> schemas) {
165
List<String> errors = new ArrayList<>();
166
List<JsonNode> validSchemas = new ArrayList<>();
167
168
for (int i = 0; i < schemas.size(); i++) {
169
JsonNode schema = schemas.get(i);
170
ProcessingReport report = syntaxValidator.validateSchema(schema);
171
172
if (report.isSuccess()) {
173
validSchemas.add(schema);
174
} else {
175
StringBuilder schemaErrors = new StringBuilder();
176
schemaErrors.append("Schema ").append(i).append(" errors:\n");
177
for (ProcessingMessage message : report) {
178
schemaErrors.append(" ").append(message.getMessage()).append("\n");
179
}
180
errors.add(schemaErrors.toString());
181
}
182
}
183
184
return new ValidationResult(validSchemas, errors);
185
}
186
187
public boolean isValidSchema(JsonNode schema) {
188
return syntaxValidator.schemaIsValid(schema);
189
}
190
}
191
192
public class ValidationResult {
193
private final List<JsonNode> validSchemas;
194
private final List<String> errors;
195
196
public ValidationResult(List<JsonNode> validSchemas, List<String> errors) {
197
this.validSchemas = validSchemas;
198
this.errors = errors;
199
}
200
201
public boolean hasErrors() {
202
return !errors.isEmpty();
203
}
204
205
public List<JsonNode> getValidSchemas() {
206
return validSchemas;
207
}
208
209
public List<String> getErrors() {
210
return errors;
211
}
212
}
213
```
214
215
### Example 3: Schema Development Tool
216
```java
217
/**
218
* Development utility for interactive schema validation
219
*/
220
public class SchemaDebugger {
221
private final SyntaxValidator syntaxValidator;
222
private final ObjectMapper mapper;
223
224
public SchemaDebugger() {
225
this.syntaxValidator = JsonSchemaFactory.byDefault().getSyntaxValidator();
226
this.mapper = new ObjectMapper();
227
}
228
229
public void debugSchema(String schemaJson) {
230
try {
231
JsonNode schema = mapper.readTree(schemaJson);
232
System.out.println("=== Schema Syntax Validation ===");
233
System.out.println("Schema:");
234
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));
235
System.out.println();
236
237
ProcessingReport report = syntaxValidator.validateSchema(schema);
238
239
if (report.isSuccess()) {
240
System.out.println("✓ Schema syntax is valid");
241
System.out.println("Schema version: " + detectSchemaVersion(schema));
242
} else {
243
System.out.println("✗ Schema syntax errors found:");
244
for (ProcessingMessage message : report) {
245
JsonNode messageJson = message.asJson();
246
String pointer = messageJson.get("instance").get("pointer").asText();
247
String error = message.getMessage();
248
249
System.out.println(" Location: " + (pointer.isEmpty() ? "/" : pointer));
250
System.out.println(" Error: " + error);
251
System.out.println();
252
}
253
}
254
255
} catch (Exception e) {
256
System.out.println("✗ Invalid JSON: " + e.getMessage());
257
}
258
}
259
260
private String detectSchemaVersion(JsonNode schema) {
261
JsonNode schemaUri = schema.get("$schema");
262
if (schemaUri != null) {
263
return schemaUri.asText();
264
}
265
return "Draft v4 (default)";
266
}
267
268
public static void main(String[] args) {
269
SchemaDebugger debugger = new SchemaDebugger();
270
271
// Test valid schema
272
String validSchema = "{\n" +
273
" \"type\": \"object\",\n" +
274
" \"properties\": {\n" +
275
" \"name\": { \"type\": \"string\" }\n" +
276
" }\n" +
277
"}";
278
debugger.debugSchema(validSchema);
279
280
// Test invalid schema
281
String invalidSchema = "{\n" +
282
" \"type\": \"object\",\n" +
283
" \"properties\": {\n" +
284
" \"age\": { \"type\": \"integer\", \"minimum\": \"invalid\" }\n" +
285
" }\n" +
286
"}";
287
debugger.debugSchema(invalidSchema);
288
}
289
}
290
```
291
292
## Syntax Validation Rules
293
294
### Type Validation Rules
295
- `type` must be a string or array of strings
296
- Valid types: `"null"`, `"boolean"`, `"object"`, `"array"`, `"number"`, `"integer"`, `"string"`
297
- Array types must contain unique values
298
299
### Numeric Constraint Rules
300
- `minimum`, `maximum` must be numbers
301
- `exclusiveMinimum`, `exclusiveMaximum` must be booleans (Draft v4) or numbers (Draft v6+)
302
- `multipleOf` must be a positive number
303
304
### String Constraint Rules
305
- `minLength`, `maxLength` must be non-negative integers
306
- `pattern` must be a valid regular expression string
307
308
### Array Constraint Rules
309
- `minItems`, `maxItems` must be non-negative integers
310
- `items` must be an object or array of objects
311
- `additionalItems` must be boolean or object
312
313
### Object Constraint Rules
314
- `properties` must be an object with schema values
315
- `patternProperties` must be an object with regex keys and schema values
316
- `additionalProperties` must be boolean or object
317
- `required` must be array of strings (Draft v4) or boolean (Draft v3)
318
- `minProperties`, `maxProperties` must be non-negative integers
319
320
## Integration with Validation
321
322
```java
323
/**
324
* Complete validation pipeline with syntax checking
325
*/
326
public class CompleteValidationPipeline {
327
private final JsonSchemaFactory factory;
328
private final SyntaxValidator syntaxValidator;
329
330
public CompleteValidationPipeline() {
331
this.factory = JsonSchemaFactory.byDefault();
332
this.syntaxValidator = factory.getSyntaxValidator();
333
}
334
335
public ProcessingReport validateWithSyntaxCheck(JsonNode schema, JsonNode instance) throws ProcessingException {
336
// Step 1: Validate schema syntax
337
ProcessingReport syntaxReport = syntaxValidator.validateSchema(schema);
338
if (!syntaxReport.isSuccess()) {
339
return syntaxReport; // Return syntax errors
340
}
341
342
// Step 2: Create schema and validate instance
343
JsonSchema jsonSchema = factory.getJsonSchema(schema);
344
return jsonSchema.validate(instance);
345
}
346
347
public ValidationResult completeValidation(JsonNode schema, JsonNode instance) {
348
try {
349
ProcessingReport report = validateWithSyntaxCheck(schema, instance);
350
return new ValidationResult(report.isSuccess(), report);
351
} catch (ProcessingException e) {
352
return new ValidationResult(false, null, e.getMessage());
353
}
354
}
355
}
356
```
357
358
## Best Practices
359
360
1. **Early Validation**: Always validate schema syntax before instance validation
361
2. **Error Reporting**: Use detailed reports to provide clear feedback on syntax issues
362
3. **Development Workflow**: Integrate syntax validation into schema development tools
363
4. **Performance**: Cache syntax validation results for frequently used schemas
364
5. **Version Awareness**: Be explicit about JSON Schema version compatibility
365
6. **Testing**: Include syntax validation in your schema test suites