pandaleague/jsonschemabuilder

Maintainers

Package info

github.com/pandaleague/JsonSchemaBuilder

pkg:composer/pandaleague/jsonschemabuilder

Transparency log

Statistics

Installs: 3 191

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v0.3.0 2026-06-15 12:33 UTC

README

A small, fluent PHP library for assembling JSON Schema documents as PHP arrays — ready to encode to JSON.

Requirements

  • PHP 8.3+
  • illuminate/contracts ^11 || ^12

Installation

composer require pandaleague/jsonschemabuilder

Quick example

use PandaLeague\JsonSchemaBuilder\Factory;

$schema = Factory::obj()
    ->title('User')
    ->description('A registered user')
    ->property('id', Factory::num()->minimum(1))
    ->property('email', Factory::str()->format('email'))
    ->property('roles', Factory::arr()
        ->items(Factory::str()->enum(['admin', 'user']))
        ->uniqueItems(true)
    )
    ->required(['id', 'email'])
    ->additionalProperties(false);

echo json_encode($schema->toArray(), JSON_PRETTY_PRINT);
{
    "type": "object",
    "title": "User",
    "description": "A registered user",
    "properties": {
        "id":    { "type": "number", "minimum": 1 },
        "email": { "type": "string", "format": "email" },
        "roles": {
            "type": "array",
            "items": {
                "type": "string",
                "enum": ["admin", "user"]
            },
            "uniqueItems": true
        }
    },
    "additionalProperties": false,
    "required": ["id", "email"]
}

Types

Every builder is created through Factory and returns a fluent instance. All builders implement Illuminate\Contracts\Support\Arrayable, so toArray() produces the final schema.

Factory Class JSON Schema type
Factory::str() aStr string
Factory::num() aNum number
Factory::bool() aBool boolean
Factory::arr() aArr array
Factory::obj() aObj object
Factory::null() aNull null

Shared keywords

Available on every builder (via the BaseType trait):

  • id(string), schema(string), title(string), description(string)
  • enum(array) — values must match the underlying type
  • anyOf(Type[]), allOf(Type[]), oneOf(Type[]), not(Type)
  • ref(string) — emitted as $ref
  • readOnly(bool), writeOnly(bool), nullable(bool)
  • link(string $rel, string $href, string $title = '', string $method = 'GET')$rel is restricted to IANA-style relations (self, create, edit, delete, replace, first, last, next, prev, collection, latest-version, search, up)

Strings — aStr

Factory::str()
    ->size(3, 32)            // minLength / maxLength
    ->pattern('^[a-z]+$')
    ->format('email')
    ->default('admin');

Numbers — aNum

Factory::num()
    ->minimum(0.5, exclusive: true)
    ->maximum(10.0)
    ->multipleOf(0.5)
    ->default(1.0);

Arrays — aArr

Factory::arr()
    ->items(Factory::str())          // single schema, or
    ->items([Factory::str(), Factory::num()], additionalItems: false) // tuple
    ->size(1, 5)                     // minItems / maxItems
    ->uniqueItems(true);

Objects — aObj

Factory::obj()
    ->property('name', Factory::str())
    ->property('age',  Factory::num())
    ->required(['name'])
    ->additionalProperties(false)        // bool or Type
    ->size(1, 10)                        // minProperties / maxProperties
    ->propertyDependency('name', ['age'])
    ->patternProperty('^x-', Factory::str())
    ->propertyNames(Factory::str()->pattern('^[a-z]+$'));

Booleans / null

Factory::bool()->default(true);
Factory::null();

Combining schemas

Factory::str()->anyOf([
    Factory::str()->format('email'),
    Factory::str()->pattern('^\+?[0-9]+$'),
]);

Development

Install dev dependencies and run the test suite:

composer install
composer test

License

MIT