PHP递归练习构建数组

[
    'one/two' => 3,
    'one/four/0' => 5,
    'one/four/1' => 6,
    'one/four/2' => 7,
    'eight/nine/ten' => 11
]

I am attempting to build the above array based on $json_str:

$json_str = '{
    "one":
    {
        "two": 3,
        "four": [ 5,6,7]
    },
    "eight":
    {
        "nine":
        {
            "ten":11
        }
    }
}';

I built a recursive function that loops thru this $json_str but so far I can only get strings to output.

How would I build an array instead echoing a string?

Also, how would I get only index values that belong in the associative index to be there.

Currently I can only get all keys to print:

one/two => 3

one/two/four/0 => 5

one/two/four/0/1 => 6

one/two/four/0/1/2 => 7

one/eight/nine/ten => 11

Below is what I have so far:

<?php

function printAll($a, $prefix = '') {

  if (!is_array($a) && !is_object($a)) {

    $prefix = rtrim($prefix, '/');

    echo $prefix . ' => ' . $a, "
";

    return;
  }

  foreach($a as $k => $v) {

    $prefix .= $k . "/";

    printAll($v, $prefix);
  }
}


$json_str = '{
                "one":
                {
                    "two": 3,
                    "four": [ 5,6,7]
                },
                "eight":
                {
                    "nine":
                    {
                        "ten":11
                    }
                }
            }';


$object = json_decode($json_str);
printAll($object);

You could use an array to hold the keys of object, instead of using a string, and array_pop() to remove the last one at the end of the loop. So you have a stack of the keys which can be used to get the breadcrumb of the JSON data.

function printAll(&$out = [], $a, $prefix = []) {
    foreach ($a as $key => $value) {
        $prefix[] = $key;  // add the key to "prefix"
        if (is_array($value) || is_object($value)) {
            printAll($out, $value, $prefix);
        }else{
            $out[implode('/', $prefix)] = $value;
        }
        // remove current key because we are no more inside it.
        array_pop($prefix);
    }
}

$json_str = '{"one": {"two": 3, "four": [ 5,6,7] }, "eight": {"nine": {"ten":11 } } }';

$object = json_decode($json_str);
$data = [];
printAll($data, $object);
print_r($data);

Outputs:

Array
(
    [one/two] => 3
    [one/four/0] => 5
    [one/four/1] => 6
    [one/four/2] => 7
    [eight/nine/ten] => 11
)

You modify $prefix inside the foreach loop. Therefore the changes will be there in each subsequent iteration of the loop. You should be fine if you cache your output in a temporary variable:

foreach($a as $k => $v) {
    $tmp = $prefix;
    $tmp .= $k . "/";
    printAll($v, $tmp);
}

Now if you want to build an array instead of echoing you can simply pass the array by reference, and build it:

function printAll($a, &$output, $prefix = '') {
  if (!is_array($a) && !is_object($a)) {
    $prefix = rtrim($prefix, '/');
    $output[]= $prefix . ' => ' . $a. "
";
    return;
  }
  foreach($a as $k => $v) {
    $tmp = $prefix;
    $tmp .= $k . "/";
    printAll($v, $output, $tmp);
  }
}

I put a demo here: https://3v4l.org/LSvZN