Преобразовать вложенный объект PHP JSON в массив PHP - PullRequest
0 голосов
/ 28 апреля 2018

Мне нужна функция, которая преобразует вложенный JSON объект / массив PHP в ассоциативный массив.

$final_array=[];
function toArray($initial,$json_object){
    foreach($json_object as $key => $value){
        if($value is string or integer or ...){  //Requires to be changed.
             $final_array[$initial.'/'.$key]=$value;
        }
        else{
             toArray($initial.'/'.$key,$value);
        }
    }
}

$json='{
    "name":{
         "first_name":"James",
         "last_name":"Bond"
     },
     "aliases":["007","Bond"],
     "profiles":[{"0":"unknown"},"007",{"2":"secret agent"}]
}';

toArray('/Bond',json_decode($json));

foreach($final_array as $key=>$value){
     echo $key.' - '.$value;
}

И желаемый выход:

/Bond/name/first_name - James
/Bond/name/last_name - Bond
/Bond/aliases/0 - 007
/Bond/aliases/1 - Bond
/Bond/profiles/0/0 - Unknown
/Bond/profiles/1 - 007
/Bond/profiles/2 - secret agent

Какие изменения я должен внести в код, чтобы получить желаемую функциональность?

Ответы [ 4 ]

0 голосов
/ 29 апреля 2018

Моя pathify() функция объявляет переменную хранения $output внутри функции, которая может получать отправленные данные из любого места в рекурсивном процессе, поскольку она может быть изменена по ссылке (обозначается символом & перед переменной).

Пока $v является массивом, функция будет вызывать себя с обновленным / расширенным значением $path. Когда $v перестает быть массивом, к значению пути добавляется -, затем $v.

Вызывая implode("\n", pathify(...)), мой подход гарантирует, что нет никаких висячих / дополнительных символов новой строки - только между видимыми строками.

Код: ( Демо )

function pathify($array, $path, &$output = []){  // declare $output as an empty array by default and modify by reference
    foreach($array as $k => $v){
        if (is_array($v)) {                      // if can recurse
            pathify($v, "$path/$k", $output);    // append key to path, access $v array
        }else{
            $output[] = "$path/$k - $v";         // push completed string to output array
        }
    }
    return $output;                              // return array of path strings
}

$json='{
    "name":{
         "first_name":"James",
         "last_name":"Bond"
     },
     "aliases":["007","Bond"],
     "profiles":[{"0":"unknown"},"007",{"2":"secret agent"}]
}';

$data = json_decode($json, true);              // decode json to an array
echo implode("\n", pathify($data, "/Bond1"));  // separate the returned string with a newline
echo "\n-------\n";
echo implode("\n", pathify([], "/Bond2"));     // separate the returned string with a newline
echo "\n-------\n";
echo implode("\n", pathify([], "/Bond3"));     // separate the returned string with a newline
echo "\n-------\n";
echo implode("\n", pathify($data, "/Bond4"));  // separate the returned string with a newline
echo "\n-------\n";
echo implode("\n", pathify($data, "/Bond5"));  // separate the returned string with a newline

Выход:

/Bond1/name/first_name - James
/Bond1/name/last_name - Bond
/Bond1/aliases/0 - 007
/Bond1/aliases/1 - Bond
/Bond1/profiles/0/0 - unknown
/Bond1/profiles/1 - 007
/Bond1/profiles/2/2 - secret agent
-------

-------

-------
/Bond4/name/first_name - James
/Bond4/name/last_name - Bond
/Bond4/aliases/0 - 007
/Bond4/aliases/1 - Bond
/Bond4/profiles/0/0 - unknown
/Bond4/profiles/1 - 007
/Bond4/profiles/2/2 - secret agent
-------
/Bond5/name/first_name - James
/Bond5/name/last_name - Bond
/Bond5/aliases/0 - 007
/Bond5/aliases/1 - Bond
/Bond5/profiles/0/0 - unknown
/Bond5/profiles/1 - 007
/Bond5/profiles/2/2 - secret agent

Большое спасибо @hanshenrik за то, что он предупредил меня о негативном влиянии на возможность повторного использования функции с моим первым ответом, в котором использовалось объявление static $output. Если вы заинтересованы в исследовании этого недостатка, пожалуйста, прочитайте следующую страницу и комментарии . static ключевое слово внутри функции?

0 голосов
/ 29 апреля 2018

Вот решение:

<?php

function getPaths($a, $output = Array(), $parents = array()) {
    // resetting path
    $path = $parents;

    // walk through the items
    foreach($a as $key => $value) {     
        if(is_array($value)) {
            $path[] = $key;
            // get the sub-items
            $output = getPaths($value, $output, $path);
        } else {
            $path[] = $key;
            // build return array
            $x = ["path" => $path, "value" => $value];
            // add that to output
            $output[] = $x;

        }
        $path = $parents; // again a reset..
    }
    return $output;
}

// usage:

$json='{
    "name":{
         "first_name":"James",
         "last_name":"Bond"
     },
     "aliases":["007","Bond"],
     "profiles":[{"0":"unknown"},"007",{"2":"secret agent"}]
}';
$array = json_decode($json, true);

foreach(getPaths($array) as $item) {
    echo "Bond/".implode("/",$item['path']) . " - {$item['value']} <br>";
}

Выход:

Бонд / имя / имя - Джеймс
Облигация / имя / фамилия - Облигация
Бонд / псевдонимы / 0 - 007
Бонд / псевдонимы / 1 - Бонд
Бонд / Профили / 0/0 - неизвестно
Бонд / Профили / 1 - 007
Связь / профили / 2/2 - секретный агент

0 голосов
/ 29 апреля 2018

это похоже на работу:

<?php
function wtf(string $root_name,Iterable $data){
    foreach($data as $name=>$val){
        if(is_iterable($val)){
            wtf($root_name."/".$name,$val);
        }else{
            echo $root_name."/$name - $val"."\n";
        }
    }
}


$json='{
    "name":{
         "first_name":"James",
         "last_name":"Bond"
     },
     "aliases":["007","Bond"],
     "profiles":[{"0":"unknown"},"007",{"2":"secret agent"}]
}';
$data=json_decode($json,true);
wtf('/bond',$data);

вывод:

/bond/name/first_name - James
/bond/name/last_name - Bond
/bond/aliases/0 - 007
/bond/aliases/1 - Bond
/bond/profiles/0/0 - unknown
/bond/profiles/1 - 007
/bond/profiles/2/2 - secret agent
0 голосов
/ 29 апреля 2018

Преобразуйте его в универсальный объектный тип данных thingie, а затем соберите его.

Это может помочь -

<?php

$json='{
    "name":{
         "first_name":"James",
         "last_name":"Bond"
     },
     "aliases":["007","Bond"],
     "profiles":[{"0":"unknown"},"007",{"2":"secret agent"}]
}';


function printobj($o){
  foreach($o as $p=>$v){
    if(is_object($v)){
     printobj($v);
    }elseif(is_array($v)){
     printobj(json_decode(json_encode($v)));
    }else{
     print $p." = ".$v."\n";
    }
  }
return;
}

$object=json_decode($json);
printobj($object);

    ?>
...