Code
This function works as same as json_decode(json_encode($arr), false).
function arrayToObject(array $arr)
{
    $flat = array_keys($arr) === range(0, count($arr) - 1);
    $out = $flat ? [] : new \stdClass();
    foreach ($arr as $key => $value) {
        $temp = is_array($value) ? $this->arrayToObject($value) : $value;
        if ($flat) {
            $out[] = $temp;
        } else {
            $out->{$key} = $temp;
        }
    }
    return $out;
}
Testing
Test 1: Flat array
$arr = ["a", "b", "c"];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));
Output:
array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)
array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)
Test 2: Array of objects
$arr = [["a" => 1], ["a" => 1], ["a" => 1]];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));
Output:
array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)
array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)
Test 3: Object
$arr = ["a" => 1];
var_export(json_decode($arr));
var_export($this->arrayToObject($arr));
Output:
stdClass::__set_state(array('a' => 1,))
stdClass::__set_state(array('a' => 1,))