create multidimensional array from json object list - php

I have a json feed that is more or less a list of objects
each has it's own id and idParent. objects that have idParent of null are the base parent elements. What I'm trying to achieve is to make a proper multidimensional array like a tree view. Keep in mind that children can have children too.
{
"obj1":{
"idParent":null,
"id":"parent1"
},
"obj2":{
"idParent":null,
"id":"parent2"
},
"obj3":{
"idParent":null,
"id":"parent3"
},
"obj4":{
"idParent":null,
"id":"parent4"
},
"obj5":{
"idParent":null,
"id":"parent5"
},
"obj6":{
"idParent":"parent1",
"id":"layer1-1"
},
"obj7":{
"idParent":"parent1",
"id":"layer1-2"
},
"obj8":{
"idParent":"parent2",
"id":"layer1-3"
},
"obj9":{
"idParent":"parent4",
"id":"layer1-4"
},
"obj10":{
"idParent":"parent3",
"id":"layer1-5"
},
"obj11":{
"idParent":"layer1-1",
"id":"layer2-1"
},
"obj12":{
"idParent":"parent5",
"id":"layer2-2"
},
"obj13":{
"idParent":"layer1-4",
"id":"layer2-3"
},
"obj14":{
"idParent":"layer1-5",
"id":"layer2-4"
},
"obj15":{
"idParent":"layer1-5",
"id":"layer2-5"
}
}
I've managed to filter out the root parents but after that I fail very bad
The first function does filter out the root parent nodes with idParent of null.
function decodeData($data) {
global $out;
foreach ($data as $key => $obj) {
if (is_array($obj)) {
foreach ($obj as $prop => $value) {
if ($prop == 'idParent') {
if($value == null) {
array_push($out, $obj);
unset($data[$key]);
}
}
}
}
}
if (count($data) > 0) {
decodeData($data);
} else {
echo json_encode(array('length'=>count($data)));
}
}
And this is what I'm experimenting on with no result
function decodeData($arrays) {
global $out;
foreach ($arrays as $array_name => $arr) {
foreach ($arr as $arr_prop => $arr_val) {
if ($arr_prop == 'idParent' && $arr_val == null) { // we found root parents
array_push($out, $arr);
unset($arrays[$array_name]); //remove array from the list
} else { // check if idParent is inside out
foreach ($out as $out_arr_name => $out_arr) { // iterate through out arrays
foreach ($out_arr as $out_arr_prop => $out_prop_val) { //
if ($out_arr_prop == 'id' && $arr_prop == 'idParent' && $out_arr_val == $arr_val) {
array_push($out_arr['children'], $obj);
unset($arrays[$array_name]);
}
}
}
}
}
}
if (count($arrays) > 0) {
decodeData($arrays);
} else {
echo json_encode(array('length'=>count($arrays)));
}
}
If anyone could provide some help I would really appreciate it.

I couldn't figure out what output do you want, so I just made a simple tree structure:
$data = json_decode( $your_json_string );
// Store each element in a lookup table indexed by element id
// 0th pass: put a fake root element there
$by_id = array(
'*' => new stdclass
);
// First pass: put each element into there
foreach( $data as $o ) $by_id[ $o->id ] = $o;
// Second pass: add each element into its parent's children array
foreach( $data as $o ){
$pid = $o->idParent ? $o->idParent : '*';
$p = $by_id[ $pid ];
$p->children[] = $o;
}
// Trash everything else, we start from the (fake) root element:
$tree = $by_id['*']->children;
/**** REVERSE ****/
$todo = $tree;
$json = array();
while( $todo ){
$o = array_shift( $todo );
if( isset( $o->children )){
$todo = array_merge( $todo, $o->children );
unset( $o->children );
}
$json[] = $o;
};
echo json_encode( $json );
The result:
http://codepad.viper-7.com/V7PjDh

Related

PHP read json file key value

Trying to read a json file and assign values to php variables.
My json file looks like this:
{
"123456": {
"fuelpump": {
"name": "Pump XX",
"address": "Address here",
"8493024" <-- I WANT THIS THE VALUE 8493024: {
"connectors": {
"8493024-1": {
"infohere": "more info here"
}
}
}
}
},
"456789": {
"fuelpump": {
"name": "Pump YY",
"address": "Address here",
"8374769" <-- I WANT THIS THE VALUE 8374769: {
"connectors": {
"8374769-1": {
"infohere": "more info here"
}
}
}
}
}
}
This is how my php code is looking:
<?php
$jsonfile = file_get_contents('jsonfile.json');
$jsonitems = json_decode($jsonfile);
foreach ($jsonitems as $location) {
$name = $location->fuelpump->name; //This works OK
$address = $location->fuelpump->address; // This ALSO OK
$fuelPumpno = $location->fuelpump[2]; //This doesnt work. Here i want the key names 8493024 and 8374769
}
How can i get the name of the keys "8493024" and "8374769"?
You have to loop over the fuelpump properties to find the value.
If that is the structure of the json object, and it does not change, you can do with this:
foreach ($location->fuelpump as $key => $value) {
if ($key !== 'name' && $key !== 'address') {
$fuelPumpno = $key;
}
}
Another way
it filters the keys of the $location object and get the first element of the result:
$fuelPumpno = current(array_filter(array_keys(get_object_vars($location->fuelpump)), function($el) {
return $el !== 'name' && $el !== 'address';
}));
Another approach is to filter only numeric values:
$jsonfile = file_get_contents('jsonfile.json');
$jsonitems = json_decode($jsonfile, true);
$pumpNo = [];
foreach ($jsonitems as $data) {
$pumpNo = array_merge($pumpNo, array_filter(array_keys($data["fuelpump"]), 'is_numeric'));
}
print_r($pumpNo);
It returns
Array
(
[0] => 8493024
[1] => 8374769
)

How to create an array from single table data with parent and child included?

I have data in a table something like in this image. In this example, 87 is the main parent which have child category 92, 97, 100. Each child can also have sub categories.
This is my code so far I have tried, but I am not able implement level 3 of the array.
public function getList(int $id): array
{
$finalArray = [];
foreach ($result as $key => $value) {
if ($value['parent_id'] === '87') {
$finalArray[$value['id']] = [
'title' => $value['title'],
'subCategory' => []
];
continue;
}
// Extract parent
$parentId = $value['parent_id'];
if ($this->multiKeyExists($finalArray, $parentId)) {
$finalArray[$parentId]['subCategory'] = [
'title' => $value['title'],
'subCategory' => []
];
}
}
}
protected function multiKeyExists(array $arr, $key)
{
if (array_key_exists($key, $arr)) {
return true;
}
foreach ($arr as $element) {
if (is_array($element) && $this->multiKeyExists($element, $key)) {
return true;
}
}
return false;
}
Expected result:
- 92
- 93
- 95
-96
Can anyone help me with a simple way to solve the problem ?
function sortResult($result,$id=87){
$finalArr=[];
$finalArr['id']=$id;
foreach($result as $key=>$val){
if($val['id']==$id){
$finalArr['title']=$val['title'];
}
if($val['parent_id']==$id){
$finalArr['subs'][$val['id']]=sortResult($result,$val['id']);
}
}
return $finalArr;
}
The recursive function will look for a child and run itself
$createtree = function ($start = NULL) use ($result,&$createtree){
$start = $start ?? 0;
$part = $result[$start];
//has childs?
if($key = array_keys(array_column($result, 'parent_id'),$part['id'] )){
$part['sub'] = array_map(function($val) use ($result,&$createtree) {
return $createtree($val);
},$key);
}
return $part;
};
print_r($createtree());
Edit: working sample
https://onlinephp.io/c/1c7dd

Search for a value in JSON using php

I have a JSON file in this format:
[
["name","purpose","description"],
["name2","purpose2","description2"],
["name3","purpose3","description3"]
]
Now, I have got the solutions for finding them by key. But, my JSON doesn't have keys. How can I search inside this JSON object to find second element by using "purpose2"? Also, I need to display the second element (i.e. "name2","purpose2","description2").
I used this function, but it's not helping me out.
function searchJson($obj, $value) {
foreach($obj as $item) {
foreach($item as $child) {
if(isset($child) && $child == $value) {
return $child;
}
}
}
return null;
}
Thanks in advance !
As the json data doesn't have string keys upon which to search you can branch the logic in the function to test for numeric indexes and then use in_array perhaps
$json = '[["name","purpose","description"],["name2","purpose2","description2"],["name3","purpose3","description3"]]';
function searchJson( $obj, $value ) {
foreach( $obj as $key => $item ) {
if( !is_nan( intval( $key ) ) && is_array( $item ) ){
if( in_array( $value, $item ) ) return $item;
} else {
foreach( $item as $child ) {
if(isset($child) && $child == $value) {
return $child;
}
}
}
}
return null;
}
$data = json_decode( $json );
$results = searchJson( $data , 'purpose2' );
print_r( $results );

PHP - recursive function foreach

I would to create a recursive function in order to retrieve data from an array and to organize then.
However I have some difficulties to create the right logic. The principle must be apply to any sub level until it ends or nothing is found.
I want to prevent this kind of code by repeating a foreach inside a foreach...:
$cats = get_categories($args);
$categories = array();
foreach($cats as $cat){
$parent = $cat->category_parent;
if ($parent) {
$categories['child'][$parent][$cat->cat_ID] = $cat->name;
} else {
$categories['parent'][$cat->cat_ID] = $cat->name;
}
}
}
if (isset($categories['parent']) && !empty($categories['parent'])) {
foreach($categories['parent'] as $id => $cat){
$new_cats[$id]['title'] = $cat;
if (isset($categories['child'][$id])) {
foreach($categories['child'][$id] as $child_id => $child_cat){
$new_cats[$child_id]['title'] = $child_cat;
$new_cats[$child_id]['parent_id'] = $id;
if (isset($categories['child'][$child_id])) {
foreach($categories['child'][$child_id] as $sub_child_id => $sub_child_cat){
$new_cats[$sub_child_id]['title'] = $sub_child_cat;
$new_cats[$sub_child_id]['parent_id'] = $child_id;
}
}
}
}
}
}
}
May be this code help you to get idea for formatting your desired array format.
<?php
// Main function
function BuildArr($arr)
{
$formattedArr = array();
if(!empty($arr))
{
foreach($arr as $val)
{
if($val['has_children'])
{
$returnArr = SubBuildArr($val['children']); // call recursive function
if(!empty($rs))
{
$formattedArr[] = $returnArr;
}
}
else
{
$formattedArr[] = $val;
}
}
}
return $formattedArr;
}
// Recursive Function( Build child )
function SubBuildArr($arr)
{
$sub_fortmattedArr = array();
if(!empty($arr))
{
foreach($arr as $val)
{
if($val['has_children'])
{
$response = SubBuildArr($val['children']); // call recursive
if(!empty($response))
{
$sub_fortmattedArr[] = $response;
}
}
else
{
$sub_fortmattedArr[] = $arr;
}
}
return $sub_fortmattedArr;
}
}
?>
I use this code for my previous project for generating categories that upto n-th level

php foreach loop not working correctly

public function include_header( $h, $h_data ) {
// Require header file
if (isset($h) && !empty($h)) {
$this->header_file = 'includes/header/'.$h;
} else { return false; }
// Pass optional array of parameters
if (isset($h_data) && is_array($h_data) && !empty($h_data)) {
// Loop through array & assign keys to appropriate class members
foreach($h_data as $key => $val) {
if ($key == 'doctype') { $this->doctype = $val; }
if ($key == 'title') { $this->title = $val; }
if ($key == 'meta') {
// The meta key is should be an array in h_data
// so, we'll have to loop through the meta array
// in order to parse the individual meta elements.
foreach($key as $meta_key => $meta_val) {
$this->error = $meta_key;
}
}
}
} else { return false; }
}
I'm trying to loop through a multidimensional array, where I have the following variable...
$h_data['meta']['individual_element']
I'm trying to loop through the 'meta', so I can access each individual value, but I'm having trouble. Please help! Thanks in advance!
foreach($key as $meta_key => $meta_val) {
$this->error = $meta_key;
}
... should be
foreach($val as $meta_key => $meta_val) {
$this->error = $meta_key;
}
if ($key == 'meta') {
// The meta key is should be an array in h_data
// so, we'll have to loop through the meta array
// in order to parse the individual meta elements.
foreach($val as $meta_key => $meta_val) { //val not key
$this->error = $meta_key;
}

Categories