
If you've been following along, you'll know I've been working up JSON schemas for an API I am developing for one of our clients... and this week, it has all been coming together nicely!
Powering payload validation with JSON Schema
In terms of JSON Schema PHP wrappers, there appear to be two choices. To evaluate the state of each project, I cloned each one, installed their dependencies and ran the tests... here's what I found:
swaggest/php-json-schema - v0.12.43
- last commit was eight months ago
- project has 480 stars on GitHub
- project has two dependencies which are abandoned
- I couldn't get the tests to run, there was a fatal error
jsonrainbow/json-schema - 6.4.2
- last commit was two months ago
- project has 3.6k stars on GitHub
- project has two dependencies which are abandoned
- I ran the tests, all 4,303 of them!
Tests: 4303, Assertions: 10473, Skipped: 53.Tests: 4303, Assertions: 10473, Skipped: 53.
I could have spent longer checking the swaggest/php-json-schema issue queue to see if there were pull requests for the issues I encountered, but I must admit, jsonrainbow/json-schema, with good test coverage and relatively recent activity was all I needed to see.
In addition, jsonrainbow/json-schema is really easy to use: I chose to create a service class with methods for validation, and have my controllers delegate off to the appropriate service class methods. Here's a sample (somewhat stripped down) of one of those methods in the validator service:
<?php
namespace Drupal\my_module\Plugin\rest\resource;
<?php
declare(strict_types=1);
namespace Drupal\my_module\Validator;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use JsonSchema\Constraints\BaseConstraint;
use JsonSchema\Validator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintViolationListInterface;
class myValidator {
public function validatePost(array $data): ConstraintViolationListInterface {
$validator = new Validator();
$validator->validate($data, (object) ['$ref' => 'file://' . $schemaDefinition]);
$violations = new ConstraintViolationList();
if ($validator->isValid() === FALSE) {
foreach ($validator->getErrors() as $violation) {
$violations->add(new ConstraintViolation($violation['message'], NULL, [], $violation['property'], $violation['pointer'], '');
}
}
return $violations;
}
}
What is really nice about this approach is that the validation is entirely (almost entirely) driven by your JSON schemas, and the schemas are cheap and easy to change... Sure, you'll likely need to do further validation on the attributes: JSON Schema can constrain values to type and range (and much more). You will know, for instance, that you have an integer and that it's greater than 1, but you'll still need to check that you can load an entity (or whatever it is that integer relates to in your system). You get the picture.
All.
Very.
Good.
Stuff.
I also spotted that the jsonrainbow/json-schema maintainer is doing some work in a new branch to support a more recent draft of the JSON schema specification, so I checked out the branch, and ran the tests. I was able fix the first test failure I came across and open a pull request for it.
Last bit of news, I got a new monitor this morning. In fact, not just any monitor, but the best monitor for programming!
Apparently.
Well, I actually got a new monitor a month or so ago, but that one had a dead pixel, so I sent it back. The replacement arrived this morning, really early this morning. A loud knock at the door stirred me from slumber. My first thought, they don't wait long... he'll already be loading it back in the van! I had no time to waste. Rushing down two flights of stairs, two, three treads a go, wrestling as I went with my octopus dressing gown: it had turned itself half-inside out and was strangling itself with the waist-belt. I reached the door out of breath, defeated in detangling, the octopus was dead.
I had no choice.
I opened the door in my underpants.
She took the obligatory "photo of goods with recipient", with a nonchalance that made me think it wasn't her first time, and drove off.
And all that for... for... guess what? Another monitor with a dead pixel.
It's never easy, is it?