Skip to content

Commit a4adcdb

Browse files
authored
Allow default with null value to be applied (#108)
1 parent 4aca4f5 commit a4adcdb

File tree

8 files changed

+79
-10
lines changed

8 files changed

+79
-10
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [0.12.31] - 2020-09-21
8+
9+
### Fixed
10+
- Missing support for `null` `default` values, [#107](https://github.com/swaggest/php-json-schema/issues/107).
11+
712
## [0.12.30] - 2020-09-09
813

914
### Added
@@ -63,6 +68,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6368
### Changed
6469
- Export `null` value instead of skipping it for properties having `null` type.
6570

71+
[0.12.31]: https://github.com/swaggest/php-json-schema/compare/v0.12.30...v0.12.31
6672
[0.12.30]: https://github.com/swaggest/php-json-schema/compare/v0.12.29...v0.12.30
6773
[0.12.29]: https://github.com/swaggest/php-json-schema/compare/v0.12.28...v0.12.29
6874
[0.12.28]: https://github.com/swaggest/php-json-schema/compare/v0.12.27...v0.12.28

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PHPSTAN_VERSION ?= 0.11.15
1+
PHPSTAN_VERSION ?= 0.12.43
22
PHPBENCH_VERSION ?= 0.16.10
33

44
deps:

phpstan.neon

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
parameters:
22
inferPrivatePropertyTypeFromConstructor: true
3+
checkMissingIterableValueType: false
4+
checkGenericClassInNonGenericObjectType: false
35
ignoreErrors:
46
- '#Access to an undefined property static\(Swaggest\\JsonSchema\\JsonSchema\)\|Swaggest\\JsonSchema\\Constraint\\Properties::#'
57
- '#Access to an undefined property .+Swaggest\\JsonSchema\\NameMirror::.+#'
68
- '#should be compatible with parameter \$properties#'
79
- '#PHPDoc tag @param references unknown parameter: \$schema#'
8-
- '#should return array<string>|null but returns array<int, int|string>#'
10+
- '#Property .+ \(array<string>\|null\) does not accept array<int, string\|false>.#'
11+
- '#should return array<string> but returns array<int, int\|string>#'
12+
- '#has no return typehint specified#'
13+
- '#with no typehint specified#'
14+
- '#has no typehint specified#'
15+
- '#Unsafe usage of new static\(\).#'

src/Constraint/Content.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static function process(Context $options, $encoding, $mediaType, $data, $
3232
throw new ContentException('Invalid base64 string');
3333
}
3434
$data = base64_decode($data);
35-
if ($data === false && !$options->skipValidation) {
35+
if ($data === false && !$options->skipValidation) { // @phpstan-ignore-line
3636
throw new ContentException('Unable to decode base64');
3737
}
3838
break;

src/HasDefault.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Swaggest\JsonSchema;
4+
5+
6+
interface HasDefault
7+
{
8+
public function hasDefault();
9+
}

src/JsonSchema.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*
1919
* // draft6
2020
* @property mixed $const
21+
*
22+
* @property mixed $default
2123
*/
2224
class JsonSchema extends ClassStructure
2325
{
@@ -47,8 +49,6 @@ class JsonSchema extends ClassStructure
4749
/** @var string */
4850
public $description;
4951

50-
public $default;
51-
5252
/** @var float|null */
5353
public $multipleOf;
5454

src/Schema.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@
3131
* Class Schema
3232
* @package Swaggest\JsonSchema
3333
*/
34-
class Schema extends JsonSchema implements MetaHolder, SchemaContract
34+
class Schema extends JsonSchema implements MetaHolder, SchemaContract, HasDefault
3535
{
3636
const ENUM_NAMES_PROPERTY = 'x-enum-names';
3737
const CONST_PROPERTY = 'const';
38+
const DEFAULT_PROPERTY = 'default';
3839

3940
const DEFAULT_MAPPING = 'default';
4041

@@ -423,7 +424,7 @@ private function processOneOf($data, Context $options, $path)
423424
try {
424425
$result = self::unboolSchema($item)->process($data, $options, $path . '->oneOf[' . $index . ']');
425426
$successes++;
426-
if ($successes > 1 || $options->skipValidation) {
427+
if ($successes > 1 || $options->skipValidation) { // @phpstan-ignore-line
427428
break;
428429
}
429430
} catch (InvalidValue $exception) {
@@ -795,9 +796,23 @@ private function processObject($data, Context $options, $path, $result = null)
795796
&& $properties !== null
796797
) {
797798
foreach ($properties as $key => $property) {
799+
$allowNull = false;
800+
if ($property instanceof HasDefault) {
801+
if (!$property->hasDefault()) {
802+
continue;
803+
}
804+
805+
$allowNull = true;
806+
}
807+
798808
// todo check when property is \stdClass `{}` here (RefTest)
799-
if ($property instanceof SchemaContract && null !== $default = $property->getDefault()) {
809+
if ($property instanceof SchemaContract) {
800810
if (!array_key_exists($key, $array)) {
811+
$default = $property->getDefault();
812+
if (null === $default && !$allowNull) { // @phpstan-ignore-line
813+
continue;
814+
}
815+
801816
$defaultApplied[$key] = true;
802817
$array[$key] = $default;
803818
}
@@ -961,6 +976,9 @@ private function processArray($data, Context $options, $path, $result)
961976
$this->items = self::unboolSchema($this->items);
962977
if ($this->items instanceof SchemaContract) {
963978
$items = array();
979+
/**
980+
* @var null|bool|Schema $additionalItems
981+
*/
964982
$additionalItems = $this->items;
965983
} elseif ($this->items === null) { // items defaults to empty schema so everything is valid
966984
$items = array();
@@ -973,7 +991,6 @@ private function processArray($data, Context $options, $path, $result)
973991

974992
/**
975993
* @var Schema|Schema[] $items
976-
* @var null|bool|Schema $additionalItems
977994
*/
978995
$itemsLen = is_array($items) ? count($items) : 0;
979996
$index = 0;
@@ -1407,6 +1424,14 @@ public function getDefault()
14071424
return $this->default;
14081425
}
14091426

1427+
/**
1428+
* @return bool
1429+
*/
1430+
public function hasDefault()
1431+
{
1432+
return array_key_exists(self::DEFAULT_PROPERTY, $this->__arrayOfData);
1433+
}
1434+
14101435
/**
14111436
* @nolint
14121437
*/

tests/src/PHPUnit/Constraint/DefaultTest.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Swaggest\JsonSchema\Tests\PHPUnit\Constraint;
44

5-
use Swaggest\JsonSchema\Constraint\Type;
65
use Swaggest\JsonSchema\Schema;
76

87
class DefaultTest extends \PHPUnit_Framework_TestCase
@@ -30,4 +29,27 @@ public function testValidDefault()
3029
$this->assertSame([], $data->foo);
3130
}
3231

32+
/**
33+
* @throws \Exception
34+
* @throws \Swaggest\JsonSchema\Exception
35+
* @throws \Swaggest\JsonSchema\InvalidValue
36+
*/
37+
public function testNullDefault()
38+
{
39+
$schema = Schema::import(json_decode(<<<'JSON'
40+
{
41+
"properties": {
42+
"foo": {
43+
"type": ["null", "integer"],
44+
"default": null
45+
}
46+
}
47+
}
48+
49+
JSON
50+
));
51+
$data = $schema->in(new \stdClass());
52+
$this->assertSame('{"foo":null}', json_encode($data));
53+
}
54+
3355
}

0 commit comments

Comments
 (0)