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 example
<?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 example
<?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, and price.
  • Mark all three fields as required.
  • Set additionalProperties to false in 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 example
<?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.