Volatile coercion does strange things to numeric array keys
dktapps opened this issue · 3 comments
Environment
- PHP: 7.2.9
- pthreads: master
- OS: windows
Reproducing Code
$data = [1, 2, 3, 4, 5];
$threaded = new \Threaded;
$threaded->data = $data;
var_dump(json_encode($data));
var_dump(json_encode($threaded->data));
Expected Output
string(11) "[1,2,3,4,5]"
string(11) "[1,2,3,4,5]"
Actual Output
string(11) "[1,2,3,4,5]"
string(31) "{"0":1,"1":2,"2":3,"3":4,"4":5}"
Hey @dktapps, this is an expected behavior, albeit getting used to. After the assignment of $data
, $threaded->data
is a Volatile object with key/value properties and no array anymore. So json_encode()
handles $threaded->data
like an object. That can be prevented by doing an explicit cast back to array at the passing of $threaded->data
:
$data = [1, 2, 3, 4, 5];
$threaded = new \Threaded;
$threaded->data = $data;
var_dump(json_encode($data));
var_dump(json_encode((array)$threaded->data));
Alternatively, a cast is possible during the assignment, but not recommended because of serialization / deserialization in the background
$data = [1, 2, 3, 4, 5];
$threaded = new \Threaded;
$threaded->data = (array)$data;
var_dump(json_encode($data));
var_dump(json_encode($threaded->data));
Yep. The reason I made this issue is because it's a confusing behaviour that I see often developers getting confused with, nobody thinks to check if an array is getting coerced by their async tasks. It is not particularly intuitive, so it would be good if there was a way to solve this.
Additionally, casting to array does not produce the expected output - and also may be a problem for nested arrays (my guys are trying to async post Discord webhook data, so this is a common problem):
<?php
$t = new Threaded;
$a = [1, 2, [3, 4], 5];
$t->a = $a;
var_dump(json_encode((array) $t->a));
var_dump(json_encode($a));
outputs
string(37) "{"2":{"0":3,"1":4},"0":1,"1":2,"3":5}"
string(13) "[1,2,[3,4],5]"