Closed abicur closed 4 years ago
When defining schema with ClassStructure
, the referencing is done automatically with PHP own object references, you just need to use SomeStructure::schema()
. Definition name is owned by that referenced class and can be customized with setFromRef
.
Also when encoding Schema
instance directly (json_encode(SomeStructure::schema())
), the root schema context is not available, so all references are inlined by value instead of being put under definitions
of root schema.
In order to maintain references it is necessary to export schema (Schema::export(SomeStructure::schema())
) before encoding.
Here is an example that may fit your needs, hope it helps.
<?php
namespace Somewhere;
use Swaggest\JsonSchema\Schema;
use Swaggest\JsonSchema\Structure\ClassStructure;
require __DIR__ . '/vendor/autoload.php';
class Address extends ClassStructure
{
public $city;
public $street;
public $addition;
/**
* @param \Swaggest\JsonSchema\Constraint\Properties|static $properties
* @param Schema $ownerSchema
*/
public static function setUpProperties($properties, Schema $ownerSchema)
{
$properties->city = Schema::string();
$properties->city->minLength = 2;
$properties->street = Schema::string();
$properties->addition = Addition::schema();
$ownerSchema->type = Schema::OBJECT;
$ownerSchema->title = 'Address';
$names = self::names();
$ownerSchema->setRequired([$names->city, $names->street, $names->addition]);
}
}
class Addition extends ClassStructure
{
public $data;
public $number;
/**
* @param \Swaggest\JsonSchema\Constraint\Properties|static $properties
* @param Schema $ownerSchema
*/
public static function setUpProperties($properties, Schema $ownerSchema)
{
$properties->data = Schema::string();
$properties->data->maxLength = 255;
$properties->number = Schema::integer();
$properties->number->maximum = 100;
$ownerSchema->title = 'Addition';
$ownerSchema->type = Schema::OBJECT;
$ownerSchema->setRequired([self::names()->data, self::names()->number]);
// By default fully qualified class name (e.g. "Somewhere\\Addition") is used as definition name.
// If namespace or class name are unwanted, custom $ref value can be used.
$ownerSchema->setFromRef('#/definitions/Addition');
}
}
// Schema export is necessary to rebuild definitions and references as part of resulting JSON.
// JSON encoding schema value directly (without exporting) inlines all references as literal values.
echo json_encode(Schema::export(Address::schema()), JSON_PRETTY_PRINT + JSON_UNESCAPED_SLASHES), PHP_EOL;
$data = json_decode('{"city": "test", "street": "some street", "addition": {"data": "", "number": "99"}}');
// PHP Fatal error: Uncaught Swaggest\JsonSchema\Exception\TypeException: Integer expected, "99" received at
// #->$ref[#/definitions/Somewhere\Address]->properties:addition->$ref[#/definitions/Addition]->properties:number
$address = Address::import($data);
Result:
{
"title": "Address",
"required": [
"city",
"street",
"addition"
],
"properties": {
"city": {
"minLength": 2,
"type": "string"
},
"street": {
"type": "string"
},
"addition": {
"$ref": "#/definitions/Addition"
}
},
"type": "object",
"definitions": {
"Addition": {
"title": "Addition",
"required": [
"data",
"number"
],
"properties": {
"data": {
"maxLength": 255,
"type": "string"
},
"number": {
"maximum": 100,
"type": "integer"
}
},
"type": "object"
}
}
}
Side notes:
self::names()
can help to maintain symbolic references to your properties (with code completion and typo-safety granted by IDE).
You may be misusing id
property of schema, in general its purpose is to create reference scopes within schemas and usually id
should be an url. There is no need to set id
unless it helps to organize custom schema discovery or resolution.
You can also have a look at json-cli to generate PHP classes like these from JSON schema.
Thank you so much for your reply. It was really quite easy. Unfortunately, the documentation does not answer these questions directly. It might be useful to add a similar example to the documentation.
Good day! I have two related tasks. The first is to generate json schema from php code and the second is to validate and import json into php classes. A schema can have several levels of nesting. One of the conditions for the generated scheme is to use common parts using the definitions section and refs. Let look to example:
By using this code I can get at output schema:
Looks good. But if I try to perform validation using the same classes I get unexpected behavior.
If I change Address class from:
$properties->addition = Schema::object()->setRef('#/definitions/Addition');
to:$properties->addition = Addition::schema();
Then validation will work correctly, but generated schema will not use refs:I think I missed some easy way to close both my needs. Please tell me where to look. Thank you in advance for your help.