From 26e8a4dfad0a24d9cbf435a8f62c005a9480e85e Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 12 Sep 2014 10:54:26 -0300 Subject: [PATCH 1/5] Resolving inner definitions on $ref's --- src/JsonSchema/RefResolver.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/JsonSchema/RefResolver.php b/src/JsonSchema/RefResolver.php index 4786a331..0d3253fc 100644 --- a/src/JsonSchema/RefResolver.php +++ b/src/JsonSchema/RefResolver.php @@ -39,6 +39,10 @@ class RefResolver * @var UriRetrieverInterface */ protected $uriRetriever = null; + + + protected $innerDefinitions = array(); + /** * @param UriRetriever $retriever @@ -109,6 +113,10 @@ public function resolve($schema, $sourceUri = null) $sourceUri = $schema->id; } + if(isset($schema->definitions)){ + $this->innerDefinitions = $schema->definitions; + } + // Resolve $ref first $this->resolveRef($schema, $sourceUri); @@ -203,9 +211,16 @@ public function resolveRef($schema, $sourceUri) if (empty($schema->$ref)) { return; } - - $refSchema = $this->fetchRef($schema->$ref, $sourceUri); + + if(strpos($schema->$ref, '#/definitions/') === 0){ + //inline definition + $tag = preg_replace('/^#\/definitions\//', '', $schema->$ref); + $refSchema = $this->innerDefinitions->$tag; + } else { + $refSchema = $this->fetchRef($schema->$ref, $sourceUri); + } unset($schema->$ref); + // Augment the current $schema object with properties fetched foreach (get_object_vars($refSchema) as $prop => $value) { From fcae137ad476f9db4c6c923bc5d34dcc4fe91684 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 20 Oct 2014 03:23:12 -0200 Subject: [PATCH 2/5] Test case for inner definitions --- tests/JsonSchema/Tests/Drafts/Draft4Test.php | 34 ++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/JsonSchema/Tests/Drafts/Draft4Test.php b/tests/JsonSchema/Tests/Drafts/Draft4Test.php index 3f1d566c..7c86ff58 100644 --- a/tests/JsonSchema/Tests/Drafts/Draft4Test.php +++ b/tests/JsonSchema/Tests/Drafts/Draft4Test.php @@ -25,5 +25,39 @@ protected function getSkippedTests() 'zeroTerminatedFloats.json' ); } + + public function testInnerDefinitions(){ + $schema = <<resolve($schemaObj); + + $schema = json_encode($schemaObj); + + $this->testValidCases('{"person": {"name" : "John Doe", "age" : 30} }', $schema); + $this->testInvalidCases('{"person": {"name" : "John Doe", "age" : "wrong"} }', $schema); + } } \ No newline at end of file From 78762b4b0736ea92013f072a22b119e8eddc5e5a Mon Sep 17 00:00:00 2001 From: Kousuke Ebihara Date: Wed, 19 Nov 2014 19:02:38 +0900 Subject: [PATCH 3/5] Improve resolution of inline dereferencing * inline dereferencing is not only for definitions * supports deep level inline dereferencing --- src/JsonSchema/RefResolver.php | 37 +++++++++++++++----- tests/JsonSchema/Tests/Drafts/Draft4Test.php | 7 ++-- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/JsonSchema/RefResolver.php b/src/JsonSchema/RefResolver.php index 0d3253fc..09fc67d0 100644 --- a/src/JsonSchema/RefResolver.php +++ b/src/JsonSchema/RefResolver.php @@ -41,7 +41,7 @@ class RefResolver protected $uriRetriever = null; - protected $innerDefinitions = array(); + protected $rootSchema; /** @@ -113,8 +113,8 @@ public function resolve($schema, $sourceUri = null) $sourceUri = $schema->id; } - if(isset($schema->definitions)){ - $this->innerDefinitions = $schema->definitions; + if (!$this->rootSchema) { + $this->rootSchema = $schema; } // Resolve $ref first @@ -211,11 +211,21 @@ public function resolveRef($schema, $sourceUri) if (empty($schema->$ref)) { return; } - - if(strpos($schema->$ref, '#/definitions/') === 0){ - //inline definition - $tag = preg_replace('/^#\/definitions\//', '', $schema->$ref); - $refSchema = $this->innerDefinitions->$tag; + + if ($schema->{$ref}[0] === '#') { + $path = substr($schema->$ref, 1); + if (empty($path)) { + return; + } + + if ($path[0] !== '/') { + return; + } + + $pathParts = explode('/', $path); + array_shift($pathParts); + + $refSchema = $this->resolveRefSegment($this->rootSchema, $pathParts); } else { $refSchema = $this->fetchRef($schema->$ref, $sourceUri); } @@ -228,6 +238,17 @@ public function resolveRef($schema, $sourceUri) } } + protected function resolveRefSegment($data, $pathParts) + { + if (empty($pathParts) || empty($data)) { + return $data; + } + + $key = array_shift($pathParts); + + return $this->resolveRefSegment(is_array($data) ? $data[$key] : $data->$key, $pathParts); + } + /** * Set URI Retriever for use with the Ref Resolver * diff --git a/tests/JsonSchema/Tests/Drafts/Draft4Test.php b/tests/JsonSchema/Tests/Drafts/Draft4Test.php index 7c86ff58..4100b16e 100644 --- a/tests/JsonSchema/Tests/Drafts/Draft4Test.php +++ b/tests/JsonSchema/Tests/Drafts/Draft4Test.php @@ -32,7 +32,8 @@ public function testInnerDefinitions(){ "type": "object", "additionalProperties":false, "properties": { - "person": { "\$ref": "#/definitions/persondef" } + "person": { "\$ref": "#/definitions/persondef" }, + "person-age": { "\$ref": "#/definitions/persondef/properties/age" } }, "definitions": { "persondef": { @@ -58,6 +59,8 @@ public function testInnerDefinitions(){ $this->testValidCases('{"person": {"name" : "John Doe", "age" : 30} }', $schema); $this->testInvalidCases('{"person": {"name" : "John Doe", "age" : "wrong"} }', $schema); + $this->testValidCases('{"person-age": 30 }', $schema); + $this->testInvalidCases('{"person-age": "wrong" }', $schema); } -} \ No newline at end of file +} From c0f3d81b3794af512536ecaa356d1b51c85262bd Mon Sep 17 00:00:00 2001 From: Kousuke Ebihara Date: Wed, 19 Nov 2014 19:20:44 +0900 Subject: [PATCH 4/5] added support for resolution of inline dereferencing with ~ or / --- src/JsonSchema/RefResolver.php | 10 +++++++++- tests/JsonSchema/Tests/Drafts/Draft4Test.php | 14 +++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/JsonSchema/RefResolver.php b/src/JsonSchema/RefResolver.php index 09fc67d0..d345e40a 100644 --- a/src/JsonSchema/RefResolver.php +++ b/src/JsonSchema/RefResolver.php @@ -244,7 +244,7 @@ protected function resolveRefSegment($data, $pathParts) return $data; } - $key = array_shift($pathParts); + $key = $this->transformKey(array_shift($pathParts)); return $this->resolveRefSegment(is_array($data) ? $data[$key] : $data->$key, $pathParts); } @@ -261,4 +261,12 @@ public function setUriRetriever(UriRetriever $retriever) return $this; } + + protected function transformKey($key) + { + return strtr($key, [ + '~1' => '/', + '~0' => '~', + ]); + } } diff --git a/tests/JsonSchema/Tests/Drafts/Draft4Test.php b/tests/JsonSchema/Tests/Drafts/Draft4Test.php index 4100b16e..9bd45e6a 100644 --- a/tests/JsonSchema/Tests/Drafts/Draft4Test.php +++ b/tests/JsonSchema/Tests/Drafts/Draft4Test.php @@ -33,7 +33,9 @@ public function testInnerDefinitions(){ "additionalProperties":false, "properties": { "person": { "\$ref": "#/definitions/persondef" }, - "person-age": { "\$ref": "#/definitions/persondef/properties/age" } + "person-age": { "\$ref": "#/definitions/persondef/properties/age" }, + "slash": { "\$ref": "#/definitions/persondef/properties/~1slash" }, + "tilde": { "\$ref": "#/definitions/persondef/properties/~0tilde" } }, "definitions": { "persondef": { @@ -45,6 +47,12 @@ public function testInnerDefinitions(){ }, "age": { "type" : "integer" + }, + "/slash": { + "type" : "integer" + }, + "~tilde": { + "type" : "integer" } } } @@ -61,6 +69,10 @@ public function testInnerDefinitions(){ $this->testInvalidCases('{"person": {"name" : "John Doe", "age" : "wrong"} }', $schema); $this->testValidCases('{"person-age": 30 }', $schema); $this->testInvalidCases('{"person-age": "wrong" }', $schema); + $this->testValidCases('{"slash": 30 }', $schema); + $this->testInvalidCases('{"slash": "wrong" }', $schema); + $this->testValidCases('{"tilde": 30 }', $schema); + $this->testInvalidCases('{"tilde": "wrong" }', $schema); } } From 2450d219d374861f734ff559d876bdcb19367793 Mon Sep 17 00:00:00 2001 From: Kousuke Ebihara Date: Thu, 20 Nov 2014 09:56:50 +0900 Subject: [PATCH 5/5] Fixed array syntax to support PHP 5.3 --- src/JsonSchema/RefResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/JsonSchema/RefResolver.php b/src/JsonSchema/RefResolver.php index d345e40a..e2048724 100644 --- a/src/JsonSchema/RefResolver.php +++ b/src/JsonSchema/RefResolver.php @@ -264,9 +264,9 @@ public function setUriRetriever(UriRetriever $retriever) protected function transformKey($key) { - return strtr($key, [ + return strtr($key, array( '~1' => '/', '~0' => '~', - ]); + )); } }