diff --git a/Makefile b/Makefile index b26bc5a4..a1810c82 100644 --- a/Makefile +++ b/Makefile @@ -41,15 +41,21 @@ 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 + +# 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 $(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/src/SpecBaseObject.php b/src/SpecBaseObject.php index 29f70b42..a86324bd 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -190,15 +190,23 @@ 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; - $j = 0; - foreach ($v as $i => $d) { - if ($j++ !== $i) { - $toObject = true; - } - if ($d instanceof SpecObjectInterface) { - $data[$k][$i] = $d->getSerializableData(); + 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) { + $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])) { + // 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) { $data[$k] = (object) $data[$k]; 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