Open ghost opened 3 years ago
Hi, additionalProperties
ignore properties defined in sub schemas (like in oneOf/...
). If you want to disallow additionalProperties
, I'd suggest to move it into every oneOf
sub schema.
Another solution could be to name properties from all sub schemas in root schema.
{
"oneOf": [
{"properties": {"a": {"type":"string", "b": {"type":"integer"}}}, "required": ["a","b"]},
{"properties": {"c": {"type":"string", "d": {"type":"integer"}}}, "required": ["c","d"]},
{"properties": {"e": {"type":"string", "f": {"type":"integer"}}}, "required": ["e","f"]}
],
"properties": {"a":{},"b":{},"c":{},"d":{},"e":{},"f":{}},
"additionalProperties": false
}
Alternatively, latest JSON schema draft has a concept of unevaluatedProperties
, but unfortunately this keyword is not yet supported by swaggest/json-schema
.
Thanks, I was absent hence the late reply. Either setting additionalProperties
to true
or redefining properties on the parent class would solve the problem that the validator complains about additional properties. However, this unfortunately does not solve my problem because I'm relying on the type of the returned object. Since the parent is oneOf I would expect that the result would be either Object1, Object2 or Object3. With the approaches to circumvent the additionalProperties problem I get the parent class type back.
Again I'm not sure if I'm trying something which is not right or not supported. I'm attaching a minimal example which maybe helps to see better what I want to achieve.
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Swaggest\JsonSchema\Structure\ClassStructure;
use Swaggest\JsonSchema\Schema;
class ParentObject extends ClassStructure
{
public static function setUpProperties($properties, Schema $ownerSchema)
{
$ownerSchema->oneOf = [
ChildObject1::schema(),
ChildObject2::schema()
];
$ownerSchema->setFromRef(self::className());
// remove comment to receive Swaggest\JsonSchema\Exception\ObjectException: Additional properties not allowed
// $ownerSchema->additionalProperties = false;
}
}
class BaseObject extends ClassStructure
{
public $baseAttr1;
public $baseAttr2;
public static function setUpProperties($properties, Schema $ownerSchema)
{
$properties->baseAttr1 = Schema::string();
$properties->baseAttr2 = Schema::integer();
$ownerSchema->type = 'object';
$ownerSchema->setFromRef(self::className());
$ownerSchema->required = [
self::names()->baseAttr1
];
$ownerSchema->additionalProperties = false;
}
}
class ChildObject1 extends BaseObject
{
public $typeSpecific;
public static function setUpProperties($properties, Schema $ownerSchema)
{
parent::setUpProperties($properties, $ownerSchema);
$properties->typeSpecific = ChildObject1TypeSpecific::schema();
$ownerSchema->required[] = self::names()->typeSpecific;
}
}
class ChildObject1TypeSpecific extends ClassStructure
{
public $child1Attr;
public static function setUpProperties($properties, Schema $ownerSchema)
{
$properties->child1Attr = Schema::integer();
$ownerSchema->type = 'object';
$ownerSchema->setFromRef(self::className());
$ownerSchema->required = [
self::names()->child1Attr
];
$ownerSchema->additionalProperties = true;
}
}
class ChildObject2 extends BaseObject
{
public $typeSpecific;
public static function setUpProperties($properties, Schema $ownerSchema)
{
parent::setUpProperties($properties, $ownerSchema);
$properties->typeSpecific = ChildObject2TypeSpecific::schema();
$ownerSchema->required[] = self::names()->typeSpecific;
}
}
class ChildObject2TypeSpecific extends ClassStructure
{
public $child2Attr;
public static function setUpProperties($properties, Schema $ownerSchema)
{
$properties->child2Attr = Schema::string();
$ownerSchema->type = 'object';
$ownerSchema->setFromRef(self::className());
$ownerSchema->required = [
self::names()->child2Attr
];
$ownerSchema->additionalProperties = true;
}
}
$input = <<<JSON
{
"baseAttr1": "baseAttr1",
"baseAttr2": 1,
"typeSpecific": {
"child2Attr": "child2Attr"
}
}
JSON;
$imported = ParentObject::import(json_decode($input));
echo get_class($imported); // = ParentObject but expecting ChildObject2
I have the following schema:
where Object1..3 extend from a base object and have a discriminator property that changes a type specific section according to its value. Currently I have the problem that despite the oneOf validation and import working correctly afterwards
processObject
is called in https://github.com/swaggest/php-json-schema/blob/master/src/Schema.php#L1204-L1206. Then the validator complains about additional properties because I set those tofalse
. If I remove that then I of course get a object back which consists only of additional properties.My question is now if the thing I try to do here is valid (in JSON Schema) and whether I'm doing something wrong. Or if the additional invokation of
processObject
should be only done as fallback if nothing else matched before.