senadir / zod-php-to-schema
Convert Zod-like PHP objects to JSON Schema definitions
Requires
- php: >=7.4
Requires (Dev)
This package is auto-updated.
Last update: 2025-07-05 12:33:49 UTC
README
Convert Zod-like PHP schema definitions to JSON Schema. This package provides a fluent API for defining schemas in PHP and converting them to JSON Schema format.
Installation
composer require nadir/zod-php-to-schema
Usage
use Zod2Schema\Zod2Schema\Z; use Zod2Schema\Zod2Schema\Schema; // By default, fields are not required $userSchema = Z::object([ 'name' => Z::string()->min(2), 'age' => Z::number()->min(0)->max(120), 'email' => Z::string()->email(), 'tags' => Z::array(Z::string()) ])->to_json_schema(); echo json_encode($userSchema, JSON_PRETTY_PRINT);
Which will output:
{ "type": "object", "properties": { "name": { "type": "string", "minLength": 2 }, "age": { "type": "number", "minimum": 0, "maximum": 120 }, "email": { "type": "string", "format": "email" }, "tags": { "type": "array", "items": { "type": "string" } } } }
You can also enable required fields globally:
use Zod2Schema\Zod2Schema\Z; use Zod2Schema\Zod2Schema\Schema; // Enable required fields globally Schema::set_require_all_fields(true); // Now all fields will be required by default, but you can mark specific fields as optional $userSchemaWithOptional = Z::object([ 'name' => Z::string()->min(2), // required 'age' => Z::number()->optional(), // optional 'email' => Z::string()->email(), // required 'tags' => Z::array(Z::string())->optional() // optional ])->to_json_schema(); echo json_encode($userSchemaWithOptional, JSON_PRETTY_PRINT);
Which will output:
{ "type": "object", "properties": { "name": { "type": "string", "minLength": 2 }, "age": { "type": "number", "minimum": 0, "maximum": 120 }, "email": { "type": "string", "format": "email" }, "tags": { "type": "array", "items": { "type": "string" } } }, "required": ["name", "email"] }
You can also define a union type:
// Define a union type $statusSchema = Z::union([ Z::literal('active'), Z::literal('inactive'), Z::literal('pending') ])->to_json_schema(); echo json_encode($statusSchema, JSON_PRETTY_PRINT);
Which will output:
{ "anyOf": [ { "type": "string", "const": "active" }, { "type": "string", "const": "inactive" }, { "type": "string", "const": "pending" } ] }
Required Fields
By default, fields are not marked as required in the generated JSON Schema. You can enable required fields globally using:
Schema::set_require_all_fields(true);
When enabled:
- All fields are required by default
- Use
optional()
to mark specific fields as optional - This applies to nested objects as well
- The setting can be toggled on/off as needed
Example with optional fields:
Schema::set_require_all_fields(true); $schema = Z::object([ 'id' => Z::number(), // required 'name' => Z::string(), // required 'nickname' => Z::string()->optional(), // optional 'contact' => Z::object([ 'email' => Z::string()->email(), // required 'phone' => Z::string()->optional() // optional ]) ])->to_json_schema();
Available Schema Types
Z::string()
- String schema with various string-specific validationsZ::number()
- Number schema with numeric validationsZ::boolean()
- Boolean schemaZ::array()
- Array schema with item type definitionsZ::object()
- Object schema with property definitionsZ::literal()
- Literal value schemaZ::union()
- Union type schema
String Schema Methods
min(int $length)
- Minimum string lengthmax(int $length)
- Maximum string lengthemail()
- Email format validationurl()
- URL format validationregex(string $pattern)
- Regular expression patternoptional()
- Mark the field as optional
Number Schema Methods
min(float $min)
- Minimum valuemax(float $max)
- Maximum valueint()
- Integer validationpositive()
- Positive number validationnegative()
- Negative number validationoptional()
- Mark the field as optional
Array Schema Methods
min(int $length)
- Minimum array lengthmax(int $length)
- Maximum array lengthnonempty()
- Array must not be emptyoptional()
- Mark the field as optional
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.