Acessing specific key/values in nested array in each iteration - php

I am only interested in keys class and score and their values in my nested array. How can I only get these keys values to be printed out?
This is my $result array.
{ "images": [ { "classifiers": [ { "classifier_id": "default", "name": "default", "classes": [ { "class": "banana", "score": 0.562, "type_hierarchy": "/fruit/banana" }, { "class": "fruit", "score": 0.788 }, { "class": "diet (food)", "score": 0.528, "type_hierarchy": "/food/diet (food)" }, { "class": "food", "score": 0.528 }, { "class": "honeydew", "score": 0.5, "type_hierarchy": "/fruit/melon/honeydew" }, { "class": "melon", "score": 0.501 }, { "class": "olive color", "score": 0.973 }, { "class": "lemon yellow color", "score": 0.789 } ] } ], "image": "fruitbowl.jpg" } ], "images_processed": 1, "custom_classes": 0}
And this is my code logic.
foreach($result as $imgage => $classifier)
{
foreach($classifier["classes"] as $clas)
{
foreach($clas as $key => $value)
{
echo $key . ": " . $value;
}
}
}

This should work for you,
<?php
$string = '{"images":[{"classifiers":[{"classifier_id":"default","name":"default","classes":[{"class":"banana","score":0.562,"type_hierarchy":"/fruit/banana"},{"class":"fruit","score":0.788},{"class":"diet (food)","score":0.528,"type_hierarchy":"/food/diet (food)"},{"class":"food","score":0.528},{"class":"honeydew","score":0.5,"type_hierarchy":"/fruit/melon/honeydew"},{"class":"melon","score":0.501},{"class":"olive color","score":0.973},{"class":"lemon yellow color","score":0.789}]}],"image":"fruitbowl.jpg"}],"images_processed":1,"custom_classes":0}';
$array = json_decode($string,1);
foreach($array['images'] as $key => $images)
{
foreach($images['classifiers'] as $key => $classes)
{
foreach($classes['classes'] as $cls_score){
echo "class = ". $cls_score['class']. " & score = ". $cls_score['score'].PHP_EOL;
}
}
}
WORKING DEMO: https://3v4l.org/vF2RL

Can you try ?
$str = '{ "images": .... }';
// get associative array from json
$result = json_decode($str, true)['images'];
foreach ($result as $imgage => $classifiers) {
foreach ($classifiers["classifiers"] as $classifier) {
foreach ($classifier["classes"] as $clas) {
foreach ($clas as $key => $value) {
// you can add condition here to target only desired keys
echo $key . ": " . $value;
}
}
}
}

Related

How can JSON key change with PHP?

I get back the data from DB with php, and I get it back as follows so I want to modify it.
This what I tried:
$result = $db->run("SELECT * FROM.....")->fetchAll();
foreach($result as $key => $val) {
$result[$key] = $result[$key]['id'];
}
I want to change the key ( 0, 1) to the id values (5, 6) Change this:
{
"0": {
"id": 5,
"date_created": "2021-08-18 03:35:31",
"status": 1
},
"1": {
"id": 6,
"date_created": "2021-08-18 03:35:55",
"status": 1
}
}
To this:
{
"5": {
"id": 5,
"date_created": "2021-08-18 03:35:31",
"status": 1
},
"6": {
"id": 6,
"date_created": "2021-08-18 03:35:55",
"status": 1
}
}
try this
$newResult = [];
foreach($result as $key => $val) {
$newResult[$val['id']] = $val;
}
print_r($newResult);

Loop in nested json array PHP

Sample of json string that receive by post is here:
[
{
"gc": [
{
"id": "1",
"ti": "title1",
"oid": 1,
"mid": "1-2",
"mc": 2,
"gct": 1,
"ma": 1,
"isu": 0
}
],
"gcm": [
{
"mid": "11",
"gcid":"1",
"sid": 58,
"msg": "msg1 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
},
{
"mid": "12",
"gcid":"1",
"sid": 58,
"msg": "msg2 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
}
],
"gcms": [
{
"id": "111",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "112",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "121",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
},
{
"id": "122",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
}
]
}
]
I use below code to loop in decoded array but only loop 1 time in array:
$json = json_decode($input, true);
foreach ($json as $value) {
$this->logger->info("Start update_new_data ->");
if (isset($value['gc'])) {
$this->logger->info("gc key exist");
foreach ($value["gc"] as $jObj) {
}
} else {
if (isset($value['gcm'])) {
$this->logger->info("gcm key exist");
foreach ($value["gcm"] as $jObj) {
}
} else {
if (isset($value['gcms'])) {
$this->logger->info("gcms key exist");
foreach ($value["gcms"] as $jObj) {
}
}
}
}
$this->logger->info("End update_new_data ->");
}
I want loop in array, if key is 'gc' loop in 'gc' array and loop again and if key is 'gcm' loop in 'gcm' array and if key is 'gcms' loop in 'gcms' array. I have to check the key because key mybe not exist in json string.
Test many code but can't solve problem.
How can i do this?
#mohammadi This Can work for you.
$json = json_decode($input, true);
$json = isset($json[0])?$json[0]:'';
$this->logger->info("Start update_new_data ->");
if(!empty($json)){
foreach ($json as $Key=>$value) {
if(isset($Key)){
if ($Key == "gc") {
$this->logger->info("gc key exist");
foreach ($value as $jObj) {
}
}
else if ($Key == "gcm") {
$this->logger->info("gcm key exist");
foreach ($value as $jObj) {
}
}
else if ($Key == "gcms") {
$this->logger->info("gcms key exist");
foreach ($value as $jObj) {
}
}
}
$this->logger->info("End update_new_data ->");
}
}
you can use this "$json = isset($json[0])?$json[0]:'';"line if you do not want to change the json structure because of the whole json date(array) inside a single array so you can get the first index of the array. if you change the json like this (shown below) then you did not require this "$json = isset($json[0])?$json[0]:'';"
$input = '{
"gc": [
{
"id": "1",
"ti": "title1",
"oid": 1,
"mid": "1-2",
"mc": 2,
"gct": 1,
"ma": 1,
"isu": 0
}
],
"gcm": [
{
"mid": "11",
"gcid":"1",
"sid": 58,
"msg": "msg1 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
},
{
"mid": "12",
"gcid":"1",
"sid": 58,
"msg": "msg2 ",
"sdt": "2018-11-12T13:58:24.627",
"ma": 20181112135822,
"isu": 0
}
],
"gcms": [
{
"id": "111",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "112",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "11"
},
{
"id": "121",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
},
{
"id": "122",
"ma": 1,
"mid": 58,
"sdt": "1",
"isu": 0,
"msf": 0,
"gcid": "1",
"cmid": "12"
}
]
}';
As per the json given in the question, the decoded array has single element which encloses all the elements. In that case, instead of looping through $json like: foreach ($json.., try looping through $json[0] like: foreach ($json[0]... And to get the key, you don't have to use array_keys, just run the loop with key like: foreach ($json[0] as $key => $value)...
I don't see any reason to use a loop for the outer array. Simply access the parts you want directly:
$json = json_decode($input, true);
$value = $json[0];
$this->logger->info("Start update_new_data ->");
if (isset($value['gc'])) {
$this->logger->info("gc key exist");
foreach ($value["gc"] as $jObj) {
}
}
if (isset($value['gcm'])) {
$this->logger->info("gcm key exist");
foreach ($value["gcm"] as $jObj) {
}
}
if (isset($value['gcms'])) {
$this->logger->info("gcms key exist");
foreach ($value["gcms"] as $jObj) {
}
}
$this->logger->info("End update_new_data ->");
This way you see your json structure more clearly (array inside an array).
Try to use array_keys for iteration:
$json = json_decode($input, true);
$json_keys = array_keys($json);
foreach ($json_keys as $json_key) {
$item = $json[$json_key];
foreach ($item as $row) {
foreach ($row as $subrow) {
echo isset($subrow['id']) ? $subrow['id'] : 'nope';
}
}
}

PHP - Moving a key within an array and flatten it

I have this array of object:
[
{
"id": 1,
"name": "Carbo",
"menus": [
{
"id": 33,
"name": "FloralWhite",
"image": {
"web": "https://lorempixel.com/640/360/food/?89722",
"mobile": "https://lorempixel.com/640/360/food/?89722",
"square": "https://lorempixel.com/640/360/food/?89722"
},
"logs": {
"price": 2
}
},
{
"id": 40,
"name": "LightGray",
"image": {
"web": "https://lorempixel.com/640/360/food/?63930",
"mobile": "https://lorempixel.com/640/360/food/?63930",
"square": "https://lorempixel.com/640/360/food/?63930"
},
"logs": {
"price": 2
}
},
]
}
]
What I want to achieve:
[
{
"id": 1,
"name": "Carbo",
"menus": [
{
"id": 33,
"name": "FloralWhite",
"image": {
"web": "https://lorempixel.com/640/360/food/?89722",
"mobile": "https://lorempixel.com/640/360/food/?89722",
"square": "https://lorempixel.com/640/360/food/?89722"
},
"price": 2
},
{
"id": 40,
"name": "LightGray",
"image": {
"web": "https://lorempixel.com/640/360/food/?63930",
"mobile": "https://lorempixel.com/640/360/food/?63930",
"square": "https://lorempixel.com/640/360/food/?63930"
},
"price": 2
},
]
}
]
I've tried using laravel collection flatten with depth but it fail
$data = collect($data->menus);
$data = $data->flatten(1);
$data->values()->all();
How can I flatten the menus['logs'] object so it can one level with menu?
Something like this should do the trick. Simply iterate over your array, set the new property and remove the one you don't want.
$data = json_decode("[{
\"id\": 1,
\"name\": \"Carbo\",
\"menus\": [
{
\"id\": 33,
\"name\": \"FloralWhite\",
\"image\": {
\"web\": \"https://lorempixel.com/640/360/food/?89722\",
\"mobile\": \"https://lorempixel.com/640/360/food/?89722\",
\"square\": \"https://lorempixel.com/640/360/food/?89722\"
},
\"logs\": {
\"price\": 2
}
},
{
\"id\": 40,
\"name\": \"LightGray\",
\"image\": {
\"web\": \"https://lorempixel.com/640/360/food/?63930\",
\"mobile\": \"https://lorempixel.com/640/360/food/?63930\",
\"square\": \"https://lorempixel.com/640/360/food/?63930\"
},
\"logs\": {
\"price\": 2
}
}
]
}]");
foreach($data as $val){
foreach($val->menus as $menuVal){
$menuVal->price = $menuVal->logs->price;
unset($menuVal->logs);
}
}
#Stefen Suhat i really don't know what is the syntax for laravel but i did it with a simple php foreach() hope this will help you, as your array's depth is long so i had gone to all the levels of your array, check code and output snippet here https://eval.in/806879
try below one:
<?php
$array = array(
array(
"id"=> 1,
"name"=> "Carbo",
"menus"=> array(
array(
"id"=> 33,
"name"=> "FloralWhite",
"image"=> array(
"web"=> "https=>//lorempixel.com/640/360/food/?89722",
"mobile"=> "https=>//lorempixel.com/640/360/food/?89722",
"square"=> "https=>//lorempixel.com/640/360/food/?89722"
),
"logs"=> array(
"price"=> 2
)
),
array(
"id"=> 40,
"name"=> "LightGray",
"image"=> array(
"web"=> "https=>//lorempixel.com/640/360/food/?63930",
"mobile"=> "https=>//lorempixel.com/640/360/food/?63930",
"square"=> "https=>//lorempixel.com/640/360/food/?63930"
),
"logs"=> array(
"price"=> 2
)
),
)
)
);
foreach($array as $key => $value){
foreach ($value as $key1 => $value1) {
if(is_array($value1) && $key1 == "menus"){
foreach($value1 as $key2 => $value2) {
foreach ($value2 as $key3 => $value3) {
if(is_array($value3) && $key3 == "logs"){
unset($array[$key][$key1][$key2][$key3]);
$array[$key][$key1][$key2] = array_merge($array[$key][$key1][$key2], $value3);
}
}
}
}
}
}
echo "array after<br>";
echo "<pre>";
print_r($array); //your array after
?>

Find a key in nested json

Below is my JSON and i wan to get all key as "node"and "id" of that node.
[
{
"id": 15,
"title": " Introduction",
"node": {
"id": 15,
"title": " Introduction",
"description": " Introduction on travelling abroad",
"media_info": " Introduction on travelling abroad",
"thumb_url": "test",
"media_url": "test"
},
"children": [
{
"id": 16,
"title": "Travel Preparation",
"node": {
"id": 16,
"title": "Travel Preparation",
"description": " Travel Preparation",
"media_info": "Travel Preparation",
"thumb_url": "test",
"media_url": "test"
},
"children": [
{
"id": 17,
"title": "The Act of Traveling",
"node": {
"id": 17,
"title": "The Act of Traveling",
"description": " The Act of Traveling",
"media_info": "The Act of Traveling",
"thumb_url": "/test",
"media_url": "test"
}
}
]
},
{
"id": 18,
"title": "Arrival at Your Destination Abroad",
"node": {
"id": 18,
"title": "Arrival at Your Destination Abroad",
"description": " Arrival at Your Destination Abroad",
"media_info": "Arrival at Your Destination Abroad",
"thumb_url": "test",
"media_url": "test"
},
"children": [
{
"id": 19,
"title": "In Your Destination Country",
"node": {
"id": 19,
"title": "In Your Destination Country",
"description": " In Your Destination Country",
"media_info": "In Your Destination Country",
"thumb_url": "http:test",
"media_url": "test"
}
}
]
}
]
}
]
========================================================================
I am using below code but it is not giving the correct output.
I want out put should be 15,16,17,18.
$obj = json_decode($config_info, true);
foreach ($obj as $key => $value) {
print_r($value['node']['id']);
}
You could try with array_walk_recursive function :
$ids = array();
$data = json_decode($json, true);
array_walk_recursive($data, function($v, $k) use (&$ids) {
if ($k === 'id') {
$ids[] = $v;
}
});
$ids = array_unique($ids);
var_dump($ids);
In your code, $value['node']['id'] refer to the ['node']['id'] key, so it will give you only one output.
In you want others, you have to fetch "children" key as well. Like this for instance :
$obj = json_decode($json, true);
foreach ($obj as $key => $value) {
echo $value['node']['id']; // return 15
$children = $value['children'];
if(is_array($children)){
foreach ($children as $child){
if(is_array($child['children'])){
foreach($child['children'] as $secondLevelChild){
echo $secondLevelChild['id'];// return 17 and 19;
}
}
echo $child['id']; // return 16 and 18
}
}
}
And you can use the same method to retrieve the 17 result as well in the second level of children key, see the code above.
Check it out:
$arr = json_decode($json, true);
$ids = array();
function get_ids($arr){
global $ids;
foreach($arr as $key => $value){
if($key == 'node')
$ids[] = $value['id'];
if(is_array($value))
get_ids($value);
}
}
get_ids($arr);
echo '<pre>';
print_r(array_unique($ids));
Result:
Array
(
[0] => 15
[2] => 16
[4] => 17
[6] => 18
[7] => 19
)

Conditionally Combine PHP Array

Is there a clean way to combine 2 PHP Arrays conditionally?
I get the following JSON-Response from both arrays separately:
1st Array:
[
{
"field": {
"id": 20,
"name": "Erfolge",
"field-id": "erfolge",
"type": "textarea"
}
},
{
"field": {
"id": 29,
"name": "Sprachen",
"field-id": "sprachen",
"type": "text"
}
}
]
2nd Array:
[
{
"field": {
"id": 20,
"name": "Erfolge",
"field-id": "erfolge",
"type": "textarea"
},
"value": "new entry"
},
{
"field": {
"id": 4,
"name": "Trikotnummer",
"field-id": "trikotnummer",
"type": "number"
},
"value": "test"
},
{
"field": {
"id": 29,
"name": "Sprachen",
"field-id": "sprachen",
"type": "text"
},
"value": "Text"
}
]
I want the following target output:
[
{
"field": {
"id": 20,
"name": "Erfolge",
"field-id": "erfolge",
"type": "textarea"
},
value: "new entry"
},
{
"field": {
"id": 29,
"name": "Sprachen",
"field-id": "sprachen",
"type": "text"
},
value: "Text"
}
]
That means it must only add the values if the field exists in the 1st array.
My current solution gives me all the fields without the correct mapping:
$fieldData = array();
foreach ($fields as $field) {
$fieldData[]['fields'] = $field->getArrayCopy();
}
// Get Values
$values = $user->getProfileFieldValue();
$fieldValue = array();
foreach ($values as $value) {
$fieldValue[] = $value->getArrayCopy();
}
$result = array_merge($fieldData, $fieldValue);
Should I use the function array_walk?
This is an expensive way to do it, it searches the second array looking for the element matching the ID from the first array.
$result = array();
foreach ($first as $e1) {
$id = $e1['field']['id'];
foreach ($secondArray as $e2) {
if ($e2['field']['id'] == $id) {
$e1['value'] = $e2['value'];
break;
}
}
$result[] = $e1;
}
If the second array is very large, you can optimize it by first creating an associative array whose key are the IDs from the second array and values are the values.
https://secure.php.net/manual/en/function.array-uintersect.php
$res = array_uintersect($arr1, $arr2, function($a, $b){
return $a['field']['id'] - $b['field']['id'];
});

Categories