http clients and apis
JSON Schema Orientation
JSON Schema is a standard way to describe the expected shape of a JSON document. It can define object properties, required fields, types, formats, arrays, enums, nested structures, and whether unknown properties are allowed.
In PHP API work, JSON Schema often appears in OpenAPI documentation, contract tests, request validation, response validation, and generated API clients.
A small schema
This schema describes a product object with an integer id, string name, and numeric price.
{
"type": "object",
"required": ["id", "name", "price"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 1 },
"price": { "type": "number", "minimum": 0 }
},
"additionalProperties": false
}
You normally use a JSON Schema validation library for this. The simplified PHP example below only demonstrates the idea of required fields.
<?php
declare(strict_types=1);
$schemaRequiredFields = ['id', 'email'];
$payload = ['id' => 42, 'email' => 'sam@example.com'];
$missing = array_diff($schemaRequiredFields, array_keys($payload));
echo $missing === [] ? 'Payload matches required fields' : 'Missing: ' . implode(', ', $missing);
// Prints:
// Payload matches required fields
What schema validation is good at
JSON Schema is good for structural rules:
- required fields
- string, number, integer, boolean, object, array, and null types
- enum values
- minimum and maximum numbers
- minimum and maximum string length
- array item shape
- nested object shape
- whether unknown fields are allowed
- basic formats such as email or date-time
It is less suitable for rules that require business context, such as "the user must own this invoice" or "this coupon is only valid for this account". Those still belong in application logic.
Schema validation and business validation work together
<?php
declare(strict_types=1);
/**
* @param array<string, mixed> $payload
* @return list<string>
*/
function simpleSchemaCheck(array $payload): array
{
$errors = [];
foreach (['id', 'name', 'price'] as $field) {
if (!array_key_exists($field, $payload)) {
$errors[] = $field . ' is required.';
}
}
if (isset($payload['price']) && (!is_int($payload['price']) && !is_float($payload['price']))) {
$errors[] = 'price must be numeric.';
}
return $errors;
}
echo json_encode(simpleSchemaCheck(['id' => 1, 'name' => 'Notebook']), JSON_THROW_ON_ERROR) . PHP_EOL;
// Prints:
// ["price is required."]
Real JSON Schema validation would produce richer error locations and messages.
additionalProperties
additionalProperties: false means fields not listed in properties are rejected. That can catch client mistakes early, but it can also make API evolution harder if clients send harmless extra values.
For public APIs, be deliberate. Some teams allow unknown fields in requests for forward compatibility. Others reject them for strict contracts.
Schema evolution
Changing a schema can break clients. Adding a new optional field is usually safer than adding a new required field. Removing a field or changing its type is usually a breaking change.
When schemas describe public API responses, treat them as contracts. Version them, review them, and test them.
PHP libraries
PHP projects usually validate JSON Schema with a library rather than hand-written code. The exact package varies by project. Look for how the existing codebase loads schemas, reports errors, and maps validation failures to API responses.
JSON Schema and OpenAPI
OpenAPI uses schema objects to describe request and response bodies. That makes schemas useful beyond runtime validation:
- generated API docs
- generated clients
- generated server stubs
- contract tests
- example validation
What to check in a project
Check which JSON Schema draft or OpenAPI version the project uses.
Check whether schemas are used only for documentation or also for runtime validation.
Check how schema validation errors are returned to clients.
Check whether unknown fields are allowed or rejected.
Check schema changes for backwards compatibility.
What you should be able to do
After this lesson, you should be able to explain what JSON Schema describes, distinguish structural validation from business validation, recognise common schema keywords, and understand why schemas are useful for documentation, contract testing, and client generation.
Practice
Task: Sketch A Product Schema
Write a small JSON Schema-style PHP array for a product payload and a simple checker for required fields.
Requirements
- Use
declare(strict_types=1);. - Describe a product object with
id,name, andprice. - Mark all three fields as required.
- Set
additionalPropertiestofalsein the schema array. - Create a simple function that checks required fields.
- Include one valid payload and one missing-field payload.
- Print the results.
Check Your Work
Run the script and confirm the missing-field payload reports exactly what is missing.
Show solution
This solution sketches a schema as a PHP array and implements only the tiny required-field check for practice.
<?php
declare(strict_types=1);
$schema = [
'type' => 'object',
'required' => ['id', 'name', 'price'],
'properties' => [
'id' => ['type' => 'integer'],
'name' => ['type' => 'string', 'minLength' => 1],
'price' => ['type' => 'number', 'minimum' => 0],
],
'additionalProperties' => false,
];
/**
* @param array{required: list<string>} $schema
* @param array<string, mixed> $payload
* @return list<string>
*/
function missingRequiredFields(array $schema, array $payload): array
{
return array_values(array_diff($schema['required'], array_keys($payload)));
}
$valid = ['id' => 1, 'name' => 'Notebook', 'price' => 9.99];
$missing = ['id' => 2, 'name' => 'Pen'];
echo json_encode(missingRequiredFields($schema, $valid), JSON_THROW_ON_ERROR) . PHP_EOL;
echo json_encode(missingRequiredFields($schema, $missing), JSON_THROW_ON_ERROR) . PHP_EOL;
// Prints:
// []
// ["price"]
In real code, use a JSON Schema validator library instead of only checking required fields by hand.
Why This Works
The schema describes the contract. The valid payload has every required field. The invalid payload proves the checker can identify a missing required field.