The ObjectSchema validates objects/DTOs with named fields. It can parse input data into stdClass objects or custom class instances.
Note: If you need an associative array as output instead of an object, use AssocSchema.
use Chubbyphp\Parsing\Parser;
$p = new Parser();
// Parse to stdClass
$schema = $p->object([
'name' => $p->string(),
'age' => $p->int(),
]);
$object = $schema->parse(['name' => 'John', 'age' => 30]);
// Returns: stdClass { name: 'John', age: 30 }class User
{
public string $name;
public int $age;
}
$schema = $p->object([
'name' => $p->string(),
'age' => $p->int(),
], User::class);
$user = $schema->parse(['name' => 'John', 'age' => 30]);
// Returns: User instance with populated propertiesreadonly class User
{
public function __construct(public string $name, public int $age)
{}
}
$schema = $p->object([
'name' => $p->string(),
'age' => $p->int(),
], User::class, true);
$user = $schema->parse(['name' => 'John', 'age' => 30]);
// Returns: User instance with populated propertiesThe ObjectSchema accepts multiple input formats:
- Arrays - Standard associative arrays
- stdClass - Anonymous objects
- Traversable - Objects implementing
\Traversable - JsonSerializable - Objects implementing
\JsonSerializable
By default, unknown fields are silently ignored. Use strict() to reject unknown fields:
$schema = $p->object(['name' => $p->string()])->strict();
$schema->parse(['name' => 'John']); // OK
$schema->parse(['name' => 'John', 'extra' => 1]); // Throws errorAllow specific unknown fields to be stripped while rejecting others:
$schema = $p->object(['name' => $p->string()])->strict(['_id', '_rev']);
$schema->parse(['name' => 'John', '_id' => '123']); // OK, _id stripped
$schema->parse(['name' => 'John', 'unknown' => 'val']); // Throws errorLike the JSON Schema additionalProperties keyword with a schema: fields without a field
schema are validated against the given schema and kept in the output as dynamic
properties. Without additionalProperties() unknown fields are silently dropped, with
strict() they are rejected (the JSON Schema additionalProperties: false case) -
combining the two throws an \InvalidArgumentException:
$schema = $p->object(['name' => $p->string()])->additionalProperties($p->float());
$schema->parse(['name' => 'John', 'score' => 1.5]);
// Returns: stdClass { name: 'John', score: 1.5 }
$schema->parse(['name' => 'John', 'score' => 'high']);
// Throws: score: Type should be "float", "string" givenThe classname must accept dynamic properties: \stdClass (the default, including
subclasses) or a class implementing __set(). It also cannot be combined with
construct: true, since an extra field would be passed as an unknown named constructor
argument. Violating either constraint throws an \InvalidArgumentException when
additionalProperties() is called.
A class marked with #[\AllowDynamicProperties] is intentionally not accepted: the
attribute only suppresses the dynamic property deprecation, it is no opt-in for
input-driven property names - a colliding declared property (private or typed) would
cause a fatal error instead of a parse error. For such classes compose instead:
$schema = $p->assoc(['name' => $p->string()])
->additionalProperties($p->float())
->postParse(static fn (array $data) => new TheClass($data));Like the JSON Schema required keyword: fields listed in required() must be present -
a missing one causes a dedicated object.missingField error. All other fields are
optional and won't appear in the output if not provided:
$schema = $p->object([
'name' => $p->string(),
'nickname' => $p->string(),
])->required(['name']);
$schema->parse(['name' => 'John']);
// Returns: stdClass { name: 'John' } - no nickname property
$schema->parse(['nickname' => 'Johnny']);
// Throws: name: Missing field "name"Without required() a missing field is parsed as null, so nullable() / default()
apply.
Retrieve the schema for a specific field:
$schema = $p->object(['name' => $p->string(), 'age' => $p->int()]);
$nameSchema = $schema->getFieldSchema('name'); // Returns StringSchemaGet all field schemas to extend or compose:
$baseSchema = $p->object([
'id' => $p->int(),
'createdAt' => $p->dateTime(),
]);
$userSchema = $p->object([
...$baseSchema->getFieldToSchema(),
'name' => $p->string(),
'email' => $p->string()->email(),
]);$createUserSchema = $p->object([
'name' => $p->string()->trim()->minLength(1)->maxLength(100),
'email' => $p->string()->trim()->toLowerCase()->email(),
'age' => $p->int()->minimum(0)->maximum(150),
])->strict();$addressSchema = $p->object([
'street' => $p->string(),
'city' => $p->string(),
'zipCode' => $p->string()->pattern('/^\d{5}$/'),
]);
$personSchema = $p->object([
'name' => $p->string(),
'address' => $addressSchema,
]);
$personSchema->parse([
'name' => 'John',
'address' => [
'street' => '123 Main St',
'city' => 'Springfield',
'zipCode' => '12345',
],
]);$schema = $p->object([
'id' => $p->int(),
'name' => $p->string(),
'bio' => $p->string()->nullable(), // Can be null
'website' => $p->string()->uri(), // Validated if present
])->required(['id', 'name', 'bio']); // website field is optional
// Valid inputs:
$schema->parse(['id' => 1, 'name' => 'John', 'bio' => null]);
$schema->parse(['id' => 1, 'name' => 'John', 'bio' => 'Hello', 'website' => 'https://example.com']);$petSchema = $p->object([
'id' => $p->string()->uuid(),
'name' => $p->string()->minLength(1),
'vaccinations' => $p->array(
$p->object([
'name' => $p->string(),
'date' => $p->dateTime(),
])
),
]);
$listRequestSchema = $p->object([
'offset' => $p->int()->minimum(0),
'limit' => $p->int()->exclusiveMinimum(0)->maximum(100),
'sort' => $p->record($p->const('asc')),
'items' => $p->array($petSchema),
]);| Code | Description |
|---|---|
object.type |
Value is not a valid object type |
object.unknownField |
Unknown field found in strict mode |
object.missingField |
Field listed in required() is missing |
Field-level errors include the field name in the error path (e.g., name, address.city).