Thinking on your feet is moving your feet
Sometimes it's a step backwards, sometimes sideways... occasionally you can do nothing more than pivot. The act of moving, no matter which direction you choose, (or pivoting, if that's all you can do), will almost always give you a fresh perspective on the challenge you're facing.
Other times it's about seeing things in a new light, or in fact, switching on the light or moving closer to it: we make decisions in the available light we have at a point in time, and time, as we all know, never stands still.
All that said, it's probably clear that I'm finishing the week in a philosophical mood: software engineering is always a journey, and I've definitely been on a journey these last couple of weeks.
Change is the only constant
If you've been following along with my developer cabin posts, you'll know that I've been building out JSON Schema for an API we're implementing. To my mind, building out the schema first is the best cheapest approach to reaching agreement with a third-party. It's the contract: we expect you to send this, and if you do, we'll respond with that. It works because it forces both parties to focus on the most important thing from the outset: the interface. The bit where two worlds collide. It's where all the friction occurs.
It can be tempting to dive into the weeds of how things are going to work under the hood. And under the hood is where the expensive-to-change stuff happens. If that's what is built first, there's the inevitable costly process of making change later. It's why we draw houses, cars, planes, many things on paper first before we build them.
It is, of course, necessary to have some idea of your models. Having a clue about the entities and relationships you need is essential and you should build them into your schema. You can't fully throw away your thinking cap. But the schema is easy and cheap to change and what's more, can be developed against whilst your client (or service) builds out their implementation.
Another benefit of this approach is that it enables you to defer the decision of what you build the "under the hood" bit in. Initially I thought I'd be building an API on top of Drupal 11, but when it came to it, when some amount of time had passed, when I was closer to the light, it became clearer that what was needed was middle-ware: a middle-ware layer to receive, validate, transform and push the data on to a back end.
More time passed, the light grew stronger, and I discovered that our client already had a middle-ware sitting in front of the back end in question. It became obvious that we should add the required endpoints to that middle-ware.
Perfect!
This is all going so well.
So it's all unicorns and rainbows, right?
Always.
All the time.
Yes.
Well, maybe not all of the time...
When working with JSON Schema, you need to pick a specification version to work with. As you will have seen if you followed that link, the published specification version is 2020-12, which was published in 2022. This is the version of the specification I chose to develop my schema with. That seems like a sensible choice in 2025, right?
The middle-ware in question is built on Serverless Framework. The basic idea being that you define your service in a serverless.yml file, and that builds out to AWS Serverless.
Furthermore, it turns out that Serverless Framework supports the use of JSON schema for validation. Woot!
# serverless.yml - this is not a working example
service: api
functions:
user:
handler: src/api/user.user
events:
- http:
path: users
method: post
private: true
request:
schema:
application/json: ${file(src/schema/user.schema.json)}Furthermore, furthermore, it turns out that AWS API Gateway supports only draft 4) of the JSON Schema specification.
But wait a minute, I hear you cry.
That specification was published in 2013, it's obsolete!
And you'd be correct.
Can you downgrade a 2020-12 schema to a draft 4 schema?
No. Not easily at least. There are tools aplenty for converting up through the specifications, but none, it seems, for converting back the other way... which makes a lot of sense when you actually think about it, because who'd wanna do that, right?
Reaching for AI, I was able to convert my 2020-12 schema files to draft 4 schema files, so I wasn't entirely blocked, but then I was faced with the prospect of having to back-fill all of the more expressive validation that I had implemented in the 2020-12 schema in the controllers. The idea of splitting the validation, making sure I wasn't duplicating or missing constraints felt like a huge pain in the arm: it certainly wasn't turning out to be the sort of surprise I like... I'd gone from winning to not winning in a very short space of time.
Time to move, to find some higher ground, pivot, turn on the light.
Taking a look from different angle
So.
How about not using the builtin validation at all?
What would it take to load the 2020-12 schema inside the controller, validate and generate an appropriate response?
Well, I can tell you... it takes this:
const Ajv = require('ajv/dist/2020');
const addFormats = require('ajv-formats');
const fs = require('fs');
exports.user = async (event) => {
let payload;
try {
payload = JSON.parse(event.body);
}
catch (error) {
// Process error, return response.
}
// Load the schema file.
const schema = JSON.parse(fs.readFileSync('./src/schemas/user.schema.json', 'utf8'));
// Set up the validator.
const ajv = new Ajv({ allErrors: true });
if (!ajv.opts) {
ajv.opts = { code: {} };
}
addFormats(ajv, ['date', 'uuid', 'email']);
// Perform validation.
const validate = ajv.compile(schema);
validate(payload);
// Process errors, return respone.
}Using AJV, with AJV-Formats I was able to use my original JSON Schema, commit my code and finish the week on a philosophical high.
I wandered lonely as a clod...
Managing your API integrations?
So, how are you doing with your API integrations?
Would your organisation or project benefit from a team of experts who are able to think on their feet? Who are skilled in finding the higher ground, seeing the real problems and have a proven track record of developing solutions that work and win?
If so, give us a holler on the ole contact form below!