Skip to content

\JsonSchema\Constraints\BaseConstraint::arrayToObjectRecursive() doesn't convert empty arrays to objects #407

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
shtrom opened this issue Apr 5, 2017 · 7 comments

Comments

@shtrom
Copy link

shtrom commented Apr 5, 2017

When an empty array is given to \JsonSchema\Constraints\BaseConstraint::arrayToObjectRecursive(), it is returned identical. This leads to issues later on when using a SchemaStorage to contain this schema. Such an empty schema is only really used for tests, but this currently requires workarounds.

The following example code

use \JsonSchema\Validator;
print_r(Validator::arrayToObjectRecursive([ "baz" => [ "bar" => "baz" ]  ])); 
print_r(Validator::arrayToObjectRecursive([]));

results in

stdClass Object
(
    [baz] => stdClass Object
        (
            [bar] => baz
        )

)
Array
(
)
@shtrom
Copy link
Author

shtrom commented Apr 5, 2017

Hum, this seems to only be on the 5.x.x branch.

Adding cast to (object) before (well, after the keyword) the return in https://github.com/justinrainbow/json-schema/blob/5.x.x/src/JsonSchema/Constraints/BaseConstraint.php#L146 seems to fix the issue.

@shtrom
Copy link
Author

shtrom commented Apr 5, 2017

Strike that, it's on 6.0.0-dev, too.

@erayd
Copy link
Contributor

erayd commented Apr 5, 2017

Thanks - fixed in #409. This will be backported to 5.x.x after merge.

@wotnak
Copy link

wotnak commented Sep 9, 2023

The issue was fixed for passing an empty array directly, but still persists for nested empty arrays.

// Directly passing an empty array.
$array = [];
$object = \JsonSchema\Validator::arrayToObjectRecursive($array);
print_r($object);
// stdClass Object
// (
// )
// Passing a nested empty array.
$array = ['shouldBeAnObject' => []];
$object = \JsonSchema\Validator::arrayToObjectRecursive($array);
print_r($object);
// stdClass Object
// (
//     [shouldBeAnObject] => Array
//         (
//         )
// )

It could be fixed by passing JSON_FORCE_OBJECT flag to json_encode used in arrayToObjectRecursive method.
https://github.com/justinrainbow/json-schema/blob/master/src/JsonSchema/Constraints/BaseConstraint.php#L145
https://www.php.net/manual/en/function.json-encode.php
https://www.php.net/manual/en/json.constants.php#constant.json-force-object

--- a/src/JsonSchema/Constraints/BaseConstraint.php
+++ b/src/JsonSchema/Constraints/BaseConstraint.php
@@ -142,7 +142,7 @@ class BaseConstraint
      */
     public static function arrayToObjectRecursive($array)
     {
-        $json = json_encode($array);
+        $json = json_encode($array, \JSON_FORCE_OBJECT);
         if (json_last_error() !== \JSON_ERROR_NONE) {
             $message = 'Unable to encode schema array as JSON';
             if (function_exists('json_last_error_msg')) {
// Passing a nested empty array after adding JSON_FORCE_OBJECT flag.
$array = ['shouldBeAnObject' => []];
$object = \JsonSchema\Validator::arrayToObjectRecursive($array);
print_r($object);
// stdClass Object
// (
//     [shouldBeAnObject] => stdClass Object
//         (
//         )
// )

@wotnak
Copy link

wotnak commented Sep 9, 2023

Although, adding JSON_FORCE_OBJECT flag would also change how nested not empty not associative arrays are treated, so probably not the best solution.

// Currently.
$array = ['key' => ['value1', 'value2']];
$object = \JsonSchema\Validator::arrayToObjectRecursive($array);
// stdClass Object
// (
//     [key] => Array
//         (
//             [0] => value1
//             [1] => value2
//         )
// )
// After adding JSON_FORCE_OBJECT flag.
$array = ['key' => ['value1', 'value2']];
$object = \JsonSchema\Validator::arrayToObjectRecursive($array);
// stdClass Object
// (
//     [key] => stdClass Object
//         (
//             [0] => value1
//             [1] => value2
//         )
// )

@plato1123
Copy link

Looks like maybe this is (maybe) still causing issues, in this case to the Drupal radix theme as documented here: https://www.drupal.org/project/radix/issues/3471900

@DannyvdSluijs
Copy link
Collaborator

I've been looking into this issue and see the fixes are part of 6.0.0. and up. The reported confirmed here the proposed fix was okay as json_decode was handling the deep casts.

@plato1123 the report you're linking to is unrelated to this issue and is actually coming from a built in protection in this library. See here.

Closing the issue for now. @shtrom if you feel this issue still needs work feel free to reopen this issue with additional information.

@DannyvdSluijs DannyvdSluijs closed this as not planned Won't fix, can't repro, duplicate, stale Feb 20, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants