json-schema icon indicating copy to clipboard operation
json-schema copied to clipboard

"Array value found, but an array is required"

Open adjenks opened this issue 6 years ago • 10 comments

I'm receiving this error message:

"Array value found, but an array is required"

I don't quite understand this error. It's saying that a property is an array, but it needs an array. It seems to me like it has what it wants. This error is not intuitive. Can someone explain to me what the library wants?

adjenks avatar Jul 18 '18 23:07 adjenks

I think I understand what's going on. It's because it is receiving an associative PHP array but it wants an indexed array. It makes it confusing because they are the same 'type' in PHP. You actually have to go through the effort to check if you want to know if something is associative vs indexed in PHP. See: https://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential So perhaps this library should say:

" Array (with non-integer keys) value found, but an array is required."

Or something of the sort.

adjenks avatar Jul 18 '18 23:07 adjenks

Can you please provide a (minimal) schema sample that produces this error?

shmax avatar Jul 19 '18 00:07 shmax

Schema (test.json):

{
	"$schema": "http://json-schema.org/draft-04/schema#",
	"type": "array",
	"items": {
		"type": "object",
		"patternProperties": {
			".*": {
				"type": "boolean"
			}
		}
	}
}

Data: {"test":true}

Code:

	$validator->validate(
		json_decode('{"test":true}',1) // Without the "1" it's a bit more clear and says Object
		,(object)['$ref' => 'file://' . realpath('./schemas/test.json')]
		,Constraint::CHECK_MODE_COERCE_TYPES | Constraint::CHECK_MODE_TYPE_CAST // coerce types for the browser.
	);

Output: {"errors":[{"detail":"Array value found, but an array is required","property":""}]}

adjenks avatar Jul 19 '18 02:07 adjenks

@adjenks Thanks for that - definitely looks like something we ought to improve on.

Out of curiosity, why are you forcing json_decode to use associative arrays instead of objects? It's not the default, and it's an unusual thing to do.

erayd avatar Jul 19 '18 02:07 erayd

I just forced json_decode to use an array to demonstrate the problem when you are already working with an array.

adjenks avatar Jul 19 '18 18:07 adjenks

Hi @adjenks, I tried to make this test fail:

public function testValidateAssociativeArray()
    {
        $value = json_decode('{"test":true}', 1);

        $schema = (object) '
        {
            "$schema": "http://json-schema.org/draft-04/schema#",
            "type": "array",
            "items": {
                "type": "object",
                "patternProperties": {
                    ".*": {
                        "type": "boolean"
                    }
                }
            }
        }';

        $validator = new Validator();
        $validator->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES | Constraint::CHECK_MODE_TYPE_CAST);
    }

but it doesn't. On which PHP version are you? I'm on PHP 7.2.

antodippo avatar Oct 30 '18 19:10 antodippo

@antodippo You can't cast a string to an object the way you are attempting to do - you just end up with an StdClass object containing a single string property, which obviously is not a sane schema.

Use json_decode(), not (object) casting.

erayd avatar Oct 30 '18 20:10 erayd

To clarify - the object that results from using (object) on a string is essentially an empty schema, against which any input is considered valid.

erayd avatar Oct 30 '18 20:10 erayd

@antodippo I was using whatever the newest PHP version was when I made the post. erayd is correct, you can't turn a string into an object. PHP tries to but it makes no sense. See this example:

php > $a = (object)'{"testing":123}';
php > var_export($a);
stdClass::__set_state(array(
   'scalar' => '{"testing":123}',
))
php > echo $a;
PHP Recoverable fatal error:  Object of class stdClass could not be converted to string in php shell code on line 1
php > echo $a->testing;
PHP Notice:  Undefined property: stdClass::$testing in php shell code on line 1

So it's not a string anymore, and it's also not a a decoded json-object. So although casting a string to an object does not initially throw an error, I'm not sure what it's useful for.

adjenks avatar Oct 30 '18 23:10 adjenks

Hi,

I have the same problem :

hydra:member[0]: Array value found, but an object is required

My json is :

{
   "@id":"\/product_variants",
   "@type":"hydra:Collection",
   "hydra:member":[
      {
         "@id":"\/product_variants\/my_product",
         "@type":"ProductVariant",
         "code":"my_product",
         "position":0,
         "createdAt":"2019-08-05T16:09:13+00:00",
         "updatedAt":null,
         "optionsValues":[
            {
               "@id":"\/product_option_values\/1",
               "code":"age_class_children",
               "optionCode":"age_class",
               "position":0
            },
            {
               "@id":"\/product_option_values\/3",
               "code":"class_ordinary",
               "optionCode":"class",
               "position":1
            },
            {
               "@id":"\/product_option_values\/5",
               "code":"duration_seven",
               "optionCode":"duration",
               "position":2
            }
         ]
      }
   ]
}

And my simplified shcema in order to get the error :

{
  "type": "object",
    "required": [
    "@id",
    "@type",
    "hydra:member"
  ],
 "properties": {
 "hydra:member": {
   "type": "array",
   "items": {
     "type": "object",
     "required": [
       "@id",
       "@type",
       "code",
       "position",
       "createdAt",
        "updatedAt",
        "optionsValues"
       ]
     }
   }
 }
 }

How can we validate a collection of object ?

EDIT : sorry it's not really the same issue. If I indicate that my type is an array for my hydra:member items, the schema is valid. But for me this should be an object.

FabienSalles avatar Aug 06 '19 11:08 FabienSalles