4

When you do array type-casting of json_decoded value (with $assoc = false), PHP creates an array with string indices:

$a = (array)json_decode('{"7":"value1","8":"value2","9":"value3","13":"value4"}');

var_export($a);

//array (
//  '7' => 'value1',
//  '8' => 'value2',
//  '9' => 'value3',
//  '13' => 'value4',
//)

And for some reason these indices are not accessible:

var_dump(isset($a[7]), isset($a['7']));

//false
//false

When you try to create the same array by PHP itself, it is being created with numeric indices (string are automatically converted), and values are accessible using both strings and numbers:

$c = array('7' => 'value1', '8' => 'value2', '9' => 'value3','10' => 'value4');

var_export($c);

var_dump(isset($c[7]), isset($c['7']));

//array (
//  7 => 'value1',
//  8 => 'value2',
//  9 => 'value3',
//  13 => 'value4',
//)
//
//true
//true

Does anybody know what is going on here? Is it some bug of older PHP versions (the issue seems to be fixed on PHP version >= 7.2, but I can't find anything related in changelog)?

Here's the demo of what is going on: https://3v4l.org/da9CJ.

Gino Pane
  • 4,740
  • 5
  • 31
  • 46

3 Answers3

3

This seems to be related to bug #61655 fixed in 7.2.0:

in a object property lookup by name always in string, but in array numeric string(like "22200" ) key will transform to numeric but not a string anymore. when conversion internal HashTable did't changed so after conversion, key lookup will fail.

Clarified: $a["2000"] is always interpreted as $a[2000], but (array) failed to cast object string keys to numbers. So the array contained string numeric indices, but the array syntax' automatic casting prevented those from being accessible.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Indeed! Thanks, I looked for something related to "json_decode", not for generic type-casting. – Gino Pane Jan 22 '18 at 11:09
  • @GinoPane i will recomend you to always use `true` when you need type casting. Check once my answer as two different version are working perfectly fine. – Alive to die - Anant Jan 22 '18 at 11:10
  • 1
    @AlivetoDie, thanks! Actually, I do use it (you can check my demo link and see the test-case with `true` passed). The reason for the question was, that I faced `json_decode` usage without second parameter and couldn't explain the magic with array indices. – Gino Pane Jan 22 '18 at 11:15
0

add TRUE to json_decode()

<?php
$a = json_decode('{"7":"value1","8":"value2","9":"value3","13":"value4"}',TRUE);

var_export($a);

var_dump(isset($a[7]), isset($a['7']));

https://3v4l.org/YuF9B

Alive to die - Anant
  • 70,531
  • 10
  • 51
  • 98
Abanoub Makram
  • 463
  • 2
  • 13
0

add TRUE to json_decode() is possible, but it will couse to recode everything.

Becouse you have to change the access to the variables.

if your json look like this:

$return = '{"status":"ok","message":"","code":"200","data":{"1234":{"sid":1,"name":"foo"},"4321":{"sid":2,"name":"bar"}}}';

on:

$json_data = json_decode($return, true);
$data = $json_data['data'];

you can loop the $data and have to access the values as array: $data[0]['name'] ...

on:

$json_data = json_decode($return);
$data = (array) $json_data->data;

you can loop the $data and have to access the values as objects: $data[0]->name ...

Andreas
  • 33
  • 5