diff --git a/README.md b/README.md index eb23097..39cfb8a 100644 --- a/README.md +++ b/README.md @@ -308,7 +308,7 @@ User::export($user); // Exception: Required property missing: id at #->propertie #### Nested structures -Nested structures allow you to make composition: flatten several objects in one and separate back. +Nested structures allow you to make composition: flatten several objects in one and separate back. For nested structures that exceed a depth of the default 200 recursion limit, submit a Context maxNestLevel of an appropriate amount. ```php $user = new User(); @@ -462,7 +462,8 @@ $this->assertSame(4, $res->one); #### Overriding mapping classes If you want to map data to a different class you can register mapping at top level of your importer structure. - +Additionally, you can use the option property, maxNestLevel to increase your depth beyond the default 200 which may be +useful for certain complex Schema's. ```php class CustomSwaggerSchema extends SwaggerSchema { @@ -470,6 +471,7 @@ class CustomSwaggerSchema extends SwaggerSchema { if ($options === null) { $options = new Context(); + $options->maxNestLevel = 500; } $options->objectItemClassMapping[Schema::className()] = CustomSchema::className(); return parent::import($data, $options); diff --git a/src/Context.php b/src/Context.php index fff2862..c25ef96 100644 --- a/src/Context.php +++ b/src/Context.php @@ -4,6 +4,8 @@ class Context extends MagicMap { + const DEFAULT_MAX_NEST = 200; + public $import = true; /** @var DataPreProcessor */ @@ -51,6 +53,9 @@ class Context extends MagicMap public $isRef = false; + /** @var int property max recursive nesting depth */ + public $maxNestLevel = self::DEFAULT_MAX_NEST; + /** * Dereference $ref unless there is a $ref property defined with format not equal to `uri-reference`. * Default JSON Schema behavior is to dereference only if there is a $ref property defined with format @@ -134,4 +139,4 @@ public function withDefault() } -} \ No newline at end of file +} diff --git a/src/RefResolver.php b/src/RefResolver.php index 0601d75..a7db596 100644 --- a/src/RefResolver.php +++ b/src/RefResolver.php @@ -13,6 +13,7 @@ class RefResolver public $url; /** @var null|RefResolver */ private $rootResolver; + private int $maxNestLevel = 200; //Change this via options submitted to ::import if needed /** * @param mixed $resolutionScope @@ -102,9 +103,10 @@ public function setupResolutionScope($id, $data) * RefResolver constructor. * @param JsonSchema $rootData */ - public function __construct($rootData = null) + public function __construct($rootData = null, int $maxNestLevel = 200) { $this->rootData = $rootData; + $this->maxNestLevel = $max_nest_level; } public function setRootData($rootData) @@ -224,8 +226,8 @@ public function resolveReference($referencePath) */ public function preProcessReferences($data, Context $options, $nestingLevel = 0) { - if ($nestingLevel > 200) { - throw new Exception('Too deep nesting level', Exception::DEEP_NESTING); + if ($nestingLevel > $this->maxNestLevel) { //Updated due to specific recursion depth from Amazon product JSON Schemas - yep 200 was not enough + throw new Exception('Too deep nesting level. Nesting / Recursion level (' . $nestingLevel . ') exceeds ' . $this->maxNestLevel , Exception::DEEP_NESTING); } if (is_array($data)) { foreach ($data as $key => $item) { @@ -264,4 +266,4 @@ public function preProcessReferences($data, Context $options, $nestingLevel = 0) } -} \ No newline at end of file +} diff --git a/src/Schema.php b/src/Schema.php index ff07f0c..e9ffa3b 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -165,7 +165,7 @@ public function in($data, ?Context $options = null) $options->import = true; if ($options->refResolver === null) { - $options->refResolver = new RefResolver($data); + $options->refResolver = new RefResolver($data, $options->maxNestLevel ?? Context::DEFAULT_MAX_NEST); } else { $options->refResolver->setRootData($data); }