From 874984d7a0f816e950a16c97f0ce5f7b89d20036 Mon Sep 17 00:00:00 2001 From: James Collins Date: Fri, 8 Oct 2021 15:00:29 +0800 Subject: [PATCH 1/3] Add test to demonstrate OpenAPI v3.0 schema validation fails with empty Path properties --- Makefile | 2 ++ tests/spec/data/empty-maps.json | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/spec/data/empty-maps.json diff --git a/Makefile b/Makefile index b26bc5a4..b5de2e92 100644 --- a/Makefile +++ b/Makefile @@ -45,11 +45,13 @@ test: $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --verbose --colors=always $(TESTCASE) $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/recursion.json $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/recursion2.yaml + $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/empty-maps.json lint: install $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/reference/playlist.json $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/recursion.json $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/recursion2.yaml + $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/empty-maps.json $(DOCKER_NODE) yarn run speccy lint tests/spec/data/reference/playlist.json $(DOCKER_NODE) yarn run speccy lint tests/spec/data/recursion.json diff --git a/tests/spec/data/empty-maps.json b/tests/spec/data/empty-maps.json new file mode 100644 index 00000000..51b1eee7 --- /dev/null +++ b/tests/spec/data/empty-maps.json @@ -0,0 +1,22 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "test", + "version": "1.0" + }, + "paths": { + "/products": { + "description": "default", + "get": { + "responses": { + "200": { + "description": "Products", + "headers": {}, + "content": {}, + "links": {} + } + } + } + } + } +} \ No newline at end of file From 331fd7d3dc08b0f01f38717d975df7a8591a54e4 Mon Sep 17 00:00:00 2001 From: James Collins Date: Fri, 8 Oct 2021 15:13:53 +0800 Subject: [PATCH 2/3] During serialization convert empty Map fields to empty Objects Otherwise these fail validation against the OpenAPI v3.0 schema. --- src/SpecBaseObject.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/SpecBaseObject.php b/src/SpecBaseObject.php index 29f70b42..6dbd9488 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -191,14 +191,19 @@ public function getSerializableData() $data[$k] = $v->getSerializableData(); } elseif (is_array($v)) { $toObject = false; - $j = 0; - foreach ($v as $i => $d) { - if ($j++ !== $i) { - $toObject = true; - } - if ($d instanceof SpecObjectInterface) { - $data[$k][$i] = $d->getSerializableData(); + if (!empty($v)) { + $j = 0; + foreach ($v as $i => $d) { + if ($j++ !== $i) { + $toObject = true; + } + if ($d instanceof SpecObjectInterface) { + $data[$k][$i] = $d->getSerializableData(); + } } + } elseif (isset($this->attributes()[$k]) && is_array($this->attributes()[$k]) && 2 === count($this->attributes()[$k])) { + // An empty Map, which is an empty array in PHP but needs to be an empty object in output. + $toObject = true; } if ($toObject) { $data[$k] = (object) $data[$k]; From 1bd42dd4800f37924dfb3f41b3b5ac8a83cae251 Mon Sep 17 00:00:00 2001 From: Carsten Brandt Date: Wed, 9 Feb 2022 12:20:26 +0100 Subject: [PATCH 3/3] add comments, optimize tests for #125 --- Makefile | 12 ++++++++---- src/SpecBaseObject.php | 5 ++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index b5de2e92..a1810c82 100644 --- a/Makefile +++ b/Makefile @@ -41,11 +41,15 @@ install: composer.lock yarn.lock $(DOCKER_PHP) composer install --prefer-dist --no-interaction --no-progress --ansi $(DOCKER_NODE) yarn install -test: +test: unit test-recursion.json test-recursion2.yaml test-empty-maps.json + +unit: $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --verbose --colors=always $(TESTCASE) - $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/recursion.json - $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/recursion2.yaml - $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/empty-maps.json + +# test specific JSON files in tests/spec/data/ +# e.g. test-recursion will run validation on tests/spec/data/recursion.json +test-%: tests/spec/data/% + $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate $< lint: install $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) bin/php-openapi validate tests/spec/data/reference/playlist.json diff --git a/src/SpecBaseObject.php b/src/SpecBaseObject.php index 6dbd9488..a86324bd 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -190,8 +190,11 @@ public function getSerializableData() if ($v instanceof SpecObjectInterface) { $data[$k] = $v->getSerializableData(); } elseif (is_array($v)) { + // test if php arrays should be represented as object in YAML/JSON $toObject = false; if (!empty($v)) { + // case 1: non-empty array should be an object if it does not contain + // consecutive numeric keys $j = 0; foreach ($v as $i => $d) { if ($j++ !== $i) { @@ -202,7 +205,7 @@ public function getSerializableData() } } } elseif (isset($this->attributes()[$k]) && is_array($this->attributes()[$k]) && 2 === count($this->attributes()[$k])) { - // An empty Map, which is an empty array in PHP but needs to be an empty object in output. + // case 2: Attribute type is an object (specified in attributes() by an array which specifies two items (key and value type) $toObject = true; } if ($toObject) {