JSON Schema validation is a crucial part of many applications, ensuring data integrity and consistency. The Opis JSON Schema library (version 2.3) is a powerful tool for this purpose, but it comes with some nuances that aren’t immediately obvious. In this post, we’ll explore how to effectively use Opis for JSON validation, with a focus on error handling and reporting.
Setting Up
First, make sure you have Opis JSON Schema installed. You can do this via Composer:
composer require "opis/json-schema:^2.3"
Basic Usage
Let’s start with a real-world example. We’ll validate a user profile against a schema:
use Opis\JsonSchema\Validator;
$validator = new Validator();
$schema = json_decode('{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"profile": {
"type": "object",
"properties": {
"first": {
"type": ["string", "null"]
},
"last": {
"type": ["string", "null"]
},
"mobile_phone": {
"type": ["string", "null"],
"pattern": "^\\d{3}-\\d{3}-\\d{4}$"
},
"zip_code": {
"type": ["string", "null"],
"pattern": "^\\d{5}(-\\d{4})?$"
}
},
"required": ["first", "last", "mobile_phone", "zip_code"]
}
},
"required": ["profile"]
}');
$data = json_decode('{
"profile": {
"first": "Jane",
"last": "Doe",
"mobile_phone": "XXX",
"zip_code": 123
}
}');
$result = $validator->validate($data, $schema);
if ($result->isValid()) {
echo "The data is valid.\n";
} else {
echo "Validation failed.\n";
}
Error Handling: The Gotchas
While the basic usage is straightforward, there are some important details to keep in mind when it comes to error handling:
1. Specifying the Number of Errors
By default, the validator stops after finding the first error. To get all errors, you need to specify a high number when creating the Validator:
$validator = new Validator(null, PHP_INT_MAX);
2. Using the ErrorFormatter
The ErrorFormatter
class provides several methods to format validation errors. Here’s how to use it:
use Opis\JsonSchema\Errors\ErrorFormatter;
$formatter = new ErrorFormatter();
$error = $result->error();
3. Different Formatting Methods
The ErrorFormatter
class offers several methods, each with its own quirks:
a. format()
$formattedErrors = $formatter->format($error, true);
This method provides errors with their JSON paths. The second argument (true
) is crucial – it ensures you get all errors, not just the first one for each path.
Output structure:
[
'/profile/mobile_phone' => [
'The string should match pattern: ^\d{3}-\d{3}-\d{4}$'
],
'/profile/zip_code' => [
'The data (integer) must match the type: string, null'
]
]
b. formatFlat()
$flatErrors = $formatter->formatFlat($error);
This method gives a simple array of all error messages, including structural errors, but without path information.
Output structure:
[
'The properties must match schema: profile',
'The properties must match schema: mobile_phone, zip_code',
'The string should match pattern: ^\d{3}-\d{3}-\d{4}$',
'The data (integer) must match the type: string, null'
]
c. formatOutput()
verboseOutput = $formatter->formatOutput($error, 'verbose');
This method provides the most detailed output, including information about the schema itself. While this can be overwhelming for simple use cases, it’s valuable for debugging complex schemas.
Putting It All Together
For a comprehensive error report, you might want to combine different formatting methods:
$validator = new Validator(null, PHP_INT_MAX);
$result = $validator->validate($data, $schema);
if (!$result->isValid()) {
$formatter = new ErrorFormatter();
$error = $result->error();
$allErrors = $formatter->formatFlat($error);
$pathErrors = $formatter->format($error, true);
echo "All errors:\n";
foreach ($allErrors as $index => $errorMessage) {
echo ($index + 1) . ". $errorMessage\n";
}
echo "\nErrors with paths:\n";
foreach ($pathErrors as $path => $errors) {
foreach ($errors as $errorMessage) {
echo "$path: $errorMessage\n";
}
}
}
This will produce output like:
All errors:
1. The properties must match schema: profile
2. The properties must match schema: mobile_phone, zip_code
3. The string should match pattern: ^\d{3}-\d{3}-\d{4}$
4. The data (integer) must match the type: string, null
Errors with paths:
/profile/mobile_phone: The string should match pattern: ^\d{3}-\d{3}-\d{4}$
/profile/zip_code: The data (integer) must match the type: string, null
This approach gives you a complete list of all errors (including structural ones) and specific errors with their exact locations in the JSON structure.
Conclusion
The Opis JSON Schema library is a powerful tool for JSON validation, but its error handling features require some careful consideration. By understanding the different formatting methods and their outputs, you can create detailed, useful error reports that make debugging and data correction much easier. Remember to always set a high error limit and use the true
flag with format()
to ensure you’re getting all the error information available.
In our example, we can clearly see that the mobile_phone
doesn’t match the required pattern, and the zip_code
is an integer instead of a string. These detailed error messages make it easy to identify and correct issues in your JSON data.
Comments are closed