PHP arrays be outputed to JSON format - php

PHP arrays
$grades = array( array( name => "tom",
grade => 'A'
),
array( name => "jeff",
grade=> 'B'
),
array( name => "lisa",
grade => 'C'
)
);
$output=array
( 'status'=>'ok',
'content'=>$grades
)
And the final JSON output I want to see would be {"status":'ok',"content":"{"tom":"A","jeff":"B","lisa":"B"}"}
The question is how should I manipulated the array so it can give me the final output like above JSON?
would json_encode($output); echo $output do the trick?
or
Do I have to do
json_encode($grades) then another json_encodes($output) but I am seeing extra \ thing like {"status":1,"content":"{\"tom\":\"A\",\"jeff\":\"B\",\"lisa\":\"B\"}"}

Try this simple command
$my_array = [
"test" => "value",
"another" => [
"fruits" => ["Apple", "Orange"]
]
];
print_r(json_encode($my_array));
It will produce
{
"test":"value",
"another":{
"fruits":["Apple","Orange"]
}
}

I don't understand why you don't write just this:
<?php
$grades = array(
array(
'name' => 'tom',
'grade' => 'A'
),
array(
'name' => 'jeff',
'grade' => 'B'
),
array(
'name' => 'lisa',
'grade' => 'C'
),
);
$output = array(
'status' => 'ok',
'content' => $grades,
);
print_r(json_decode(json_encode($output)));
It prints:
stdClass Object
(
[status] => ok
[content] => Array
(
[0] => stdClass Object
(
[name] => tom
[grade] => A
)
[1] => stdClass Object
(
[name] => jeff
[grade] => B
)
[2] => stdClass Object
(
[name] => lisa
[grade] => C
)
)
)
Isn't is the expected result?

Don't call json_encode($grades) before json_encode($output), unless you have some unmentioned reason to want the grades as a string literal instead of json object. json_encode() will recursively encode all child arrays inside $output, there's no need to encode them separately.

As you may have figured out, an array's associative keys get represented as keys in the resulting JSON object, e.g. {key1: value1, ...}, as clearly demonstrated from the output you got.
Secondly, an array containing other arrays will be represented as a list in JSON, e.g. [...]
I believe your earlier code should looked something like this:
$grades = array(
array('name' => 'tom', 'grade' => 'A'),
array('name' => 'jeff', 'grade' => 'B'),
array('name' => 'lise', 'grade' => 'C'),
);
$output = array(
'status' => 'ok',
'content' => $grades
);
echo json_encode($output);
So applying the rules I have outlined above will result in the JSON below.
{"status":"ok","content":[{"name":"tom","grade":"A"},{"name":"jeff","grade":"B"},{"name":"lise","grade":"C"}]}
I personally think you should use this since it is a better representation than the one you desire to have. However, the codes below should give you your results.
$grades = array(
'tom' => 'A',
'jeff' => 'B',
'lisa' => 'B',
);
$output = array(
'status' => 'ok',
'content' => $grades
);
echo json_encode($output);
Output:
{"status":"ok","content":{"tom":"A","jeff":"B","lisa":"B"}}

The reason you are getting the 'extra' \ is that what you say you want as output is not valid JSON. PHP's default function has it right, yours will not parse in a JSON parser.
If you really want almost-json, you'll have to roll your own.

you have to change the format of $grade array to get the desired output . try below
$grade_format= array();
foreach($grades as $k=>$v)
{
//array_push($output,$k);
$grade_format[$v['name']]=$v['grade'];
}
//echo "<pre>";
//print_r($grade_format);
$output=array
( 'status'=>'ok',
'content'=>$grade_format
);
echo "<pre>";
echo json_encode($output,JSON_FORCE_OBJECT);
//output would be
{"status":"ok","content":{"tom":"A","jeff":"B","lisa":"C"}}
is that you want??
REFERENCE

Related

How can I check index in array 2 dimensional without loop in php?

I try like this :
<?php
$list_team = array(
(object)array(
'id' => 1,
'name' => 'chelsea.jpg'
),
(object)array(
'id' => 2,
'name' => 'mu.jpg'
),
(object)array(
'id' => 3,
'name' => 'arsenal.jpg'
),
);
$team = 'chelsea.jpg';
echo '<pre>';print_r($team);echo '</pre>';
echo '<pre>';print_r($list_team);echo '</pre>';
foreach($list_team as $key => $value) {
if($value->name == $team)
$team_selected = $team;
}
echo '<pre>';print_r($team_selected);echo '</pre>';
die();
?>
If the code executed, the result like this :
chelsea.jpg
Array
(
[0] => stdClass Object ( [id] => 1
[name] => chelsea.jpg
)
[1] => stdClass Object
(
[id] => 2
[name] => mu.jpg
)
[2] => stdClass Object
(
[id] => 3
[name] => arsenal.jpg
)
)
chelsea.jpg
The code using loop
But, I do not want to use a loop
How can I do it?
Try the following:
$key = array_search($team, array_column($list_team, 'name'));
$team_selected = $list_team[$key]->name;
This will search array with name and return the and return the key of the main array and you can use that to access the contents of the nested array and assign the value to. $team_selected
Using array_search(), and array_column()
<?php
$list_team = array(
(object)array(
'id' => 1,
'name' => 'chelsea.jpg'
),
(object)array(
'id' => 2,
'name' => 'mu.jpg'
),
(object)array(
'id' => 3,
'name' => 'arsenal.jpg'
),
);
$team = 'chelsea.jpg';
// array column, returns all value of sub array, with key name
// array_search will return key
$key = array_search($team, array_column($list_team, 'name'));
if($key!==false){
// your object will be
print_r($list_team[$key]);
// access remaining..
echo $list_team[$key]->name.' '. $list_team[$key]->id.PHP_EOL;
}
?>
If you want to access specific attributes in multidimensional arrays, you can do the following thing.
For example, return the ID of the first array:
echo $list_team[0]["id"];
Simply change the [0] to [1] or whatever to mention the array you wanna call, and then simply use the attribute. But if you wanna print the whole array, I really recommend you to stay on loops. With loops you're sure you get all elements. Lets say you hardcode it like I said and then a month later you add 10 new arrays, so you'll have to edit your whole code.

Isolate an array column containing indexed rows of data, then flatten/merge to form an array of rows

situation
I have an array result returned from an Database call. In the example below, it fetches many Genres which can have many books. Using a join, the query pulls the books from each genre at the same time. Here is a hypothetical result set:
array(
[0] => array (
'id' => 1,
'title' => 'ficton'
'modules' => array(
[0] => array(
'other_id' => 1
'other_title' => 'James Clavell'
),
[1] => array(
'other_id' => 2
'other_title' => 'Terry Pratchett'
),
[2] => array(
'other_id' => 3
'other_title' => 'Robert Ludlum'
),
),
[1] => array (
'id' => 2,
'title' => 'non-ficton'
'modules' => array(
[1] => array(
'other_id' => 5
'other_title' => 'An excessive book of excessively interesting things'
),
[2] => array(
'other_id' => 6
'other_title' => 'It\'s late, I can\'t think of what to put here'
),
)
)
)
Situation
What I would like to end up with is an array which contains only the modules as shown below:
array(
[0] => array(
'other_id' => 1
'other_title' => 'James Clavell'
),
[1] => array(
'other_id' => 2
'other_title' => 'Terry Pratchett'
),
[2] => array(
'other_id' => 3
'other_title' => 'Robert Ludlum'
),
[3] => array(
'other_id' => 5
'other_title' => 'An excessive book of excessively interesting things'
),
[4] => array(
'other_id' => 6
'other_title' => 'It\'s late, I can\'t think of what to put here'
)
)
Problem
Now, I have no problem achieving this through iteration but, feel there is a much better (undiscovered) means to achieving this.
Question
Is a shortcut to creating the desired result. The code I have so far is listed below and it's not a difficult situation to solve. I'm more just curious as to whether there is a much BETTER version of doing the following.
Ugly code that works
Here is a version of the code that 100% works but, features more iteration than I could care for.
$aryTemp = array();
foreach($aryGenres as $intKey => $aryGenre) {
foreach($aryGenre['modules'] as $aryModule) {
$aryTemp[] = $aryModule
}
}
Attempt using array map
An attempt using array map and failing horribly
$aryTemp = array();
foreach($aryGenres as $intKey => $aryGenre) {
$aryTemp[] = array_map(
function($aryRun) { return $aryRun;
},$aryGenre['modules']
}
I would love to be able to cut out the foreach loop as shown above.
PHP 5.6+:
$modules = array_merge(...array_column($arr, 'modules'));
# Allowing empty array
$modules = array_merge([], ...array_column($arr, 'modules'));
PHP 5.5:
$modules = call_user_func_array('array_merge', array_column($arr, 'modules'));
PHP ~5.4:
$modules = call_user_func_array(
'array_merge',
array_map(
function ($i) {
return $i['modules'];
},
$arr
)
);

Displaying an array inside an array?

I have an array inside an array and I'd like to simply print out the contents of it... the problem is what I'm trying doesn't work... ie
foreach($retval as $k=>$v){
if (is_array($v)){
foreach($v as $l=>$w){
echo $l . ' = ' . $w . '<br />';
}
} else {
echo $k . ' = ' . $v . '<br />';
}
Doing that however I end up with:
id = 2
name = Speakers
form_field = hidden
display_order = 0
groups = Array
So I'm not getting a foreach in that inside array.. what am I doing wrong? It seems actually that my code believes everything return is an array when I'm pretty sure that only 'groups' is an array.
the structure of the array looks like so:
array ( 0 => array ( 'id' => 2, 'name' => 'Speakers', 'form_field' => 'hidden', 'display_order' => '0', 'groups' => array ( 0 => array ( 'bit' => '1', 'name' => 'don', 'display_order' => '4', 'subscribers' => 8, ), 1 => array ( 'bit' => '2', 'name' => 'tyler', 'display_order' => '5', 'subscribers' => 0, ), 2 => array ( 'bit' => '4', 'name' => 'stephen', 'display_order' => '6', 'subscribers' => 0, ), 3 => array ( 'bit' => '8', 'name' => 'daniel', 'display_order' => '7', 'subscribers' => 0, ), 4 => array ( 'bit' => '16', 'name' => 'william', 'display_order' => '8', 'subscribers' => 0, ), 5 => array ( 'bit' => '32', 'name' => 'bobbys', 'display_order' => '9', 'subscribers' => 0, ), ), ), )
Long story short, I'm actually just trying to search this whole thing for say the name 'bobby' and get a simple true or false on whether that value exists anywhere in there.
print_r($myArray);
PHP Manual
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
would give:
Array
(
[a] => apple
[b] => banana
[c] => Array
(
[0] => x
[1] => y
[2] => z
)
)
Not sure if this is what you are looking for...
print_r() gives you a visual representation while var_export() returns valid, executable php code. Manual: var_export()
You're assuming that arrays are only doubly-nested, when $retval[<something>]['groups'] is also an array. Use recursion to handle this instead of just adding levels upon levels.
It sounds like you need to reconsider what you are trying to do.
If you just want to see what is in your array so that you know how to get at a particular piece of data, then you're probabaly after print_r, var_export or similar as mentioned above.
print_r($retval);
If you want your php script to be able to work out on it's own whether 'bobby' is in the array, then you might have some more information that will help your search. For example, do you know the structure of your array and that you're searching for a name? If so, then you only need to check the strings that are in $array[$foo]['name']. You could adapt your code like so:
foreach($retval as $k=>$v) {
if ($v['name'] == 'bobby') {
echo "Bobby is at index $k";
}
}
PHP contains lots of functions for arrays, although these tend to be for single-dimension arrays.
P.S. Please edit the structure of your array to make it easier to read.
If your goal is to understand if a value is in any nested array you can do this:
foreach($retval as $vec){
if(in_array("bobby", $vec)
do something
Use a RecursiveArrayIterator wrapped in RecursiveIteratorIterator. The syntax will then be:
$arr = array('this is your complicated multi-dimensional array');
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach($iterator as $key => $value){
echo '['.$key.'] => '.$value.'<br />';
}
You can even use $iterator->depth() to determine the depth of a current element.

(PHP) Converting an array of arrays from one format into another

I currently have an array, created from a database, an example of which looks like the following:
Array(
[0] => Array (
objectid => 2,
name => title,
value => apple
),
[1] => Array (
objectid => 2,
name => colour,
value => red
),
[2] => Array (
objectid => 3,
name => title,
value => pear
),
[3] => Array (
objectid => 3,
name => colour,
value => green
)
)
What I would like to do is group all the items in the array by their objectid, and convert the 'name' values into keys and 'value' values into values of an associative array....like below:
Array (
[0] => Array (
objectid => 2,
title => apple,
colour => red
),
[1] => Array (
objectid => 3,
title => pear,
colour => green
)
)
I've tried a few things but haven't really got anywhere.. Any ideas?
Thanks in advance
This should work with your current setup and should be able to handle as many key-value pairs as available:
<?php
$results = array(
array('objectid' => 2, 'name' => 'title', 'value' => 'apple'),
array('objectid' => 2, 'name' => 'color', 'value' => 'red'),
array('objectid' => 3, 'name' => 'title', 'value' => 'pear'),
array('objectid' => 3, 'name' => 'color', 'value' => 'green'));
$final = array();
foreach ($results as $result) {
$final[$result['objectid']]['objectid'] = $result['objectid'];
$final[$result['objectid']][$result['name']] = $result['value'];
}
print_r($final);
It would be easier to have the array keys correspond with your object id, that way you can iterate through your existing array, and add the key-value pairs for each object, like so:
$newArray = array();
foreach ($results as $result) {
if (!array_key_exists($result['objectid'], $newArray)) {
$newArray[$result['objectid'] = array();
}
foreach ($result as $key => $value) {
$newArray[$result['objectid'][$key] = $value;
}
}
Peter's method is perfectly valid, I just thought I would show a shorter version of the same thing (couldn't do in a comment)
foreach( $array as $obj ) {
if( !isset( $objects[$obj['objectid']] ) )
$objects[$obj['objectid']]['objectid'] = $obj['objectid'];
$objects[$obj['objectid']][$obj['name']] = $obj['value'];
}

Find all second level keys in multi-dimensional array in php

I want to generate a list of the second level of keys used. Each record does not contain all of the same keys. But I need to know what all of the keys are. array_keys() doesn't work, it only returns a list of numbers.
Essentially the output Im looking for is:
action, id, validate, Base, Ebase, Ftype, Qty, Type, Label, Unit
I have a large multi-dimensional array that follows the format:
Array
(
[0] => Array
(
[action] => A
[id] => 1
[validate] => yes
[Base] => Array
(
[id] => 2945
)
[EBase] => Array
(
[id] => 398
)
[Qty] => 1
[Type] => Array
(
[id] => 12027
)
[Label] => asfhjaflksdkfhalsdfasdfasdf
[Unit] => asdfas
)
[1] => Array
(
[action] => A
[id] => 2
[validate] => yes
[Base] => Array
(
[id] => 1986
)
[FType] => Array
(
[id] => 6
)
[Qty] => 1
[Type] => Array
(
[id] => 13835
)
[Label] => asdssdasasdf
[Unit] => asdger
)
)
Thanks for the help!
<?php
// Gets a list of all the 2nd-level keys in the array
function getL2Keys($array)
{
$result = array();
foreach($array as $sub) {
$result = array_merge($result, $sub);
}
return array_keys($result);
}
?>
edit: removed superfluous array_reverse() function
array_keys(call_user_func_array('array_merge', $a));
Merge all values and retrieve the resulting keys.
One liner:
$keys=array_unique(array_reduce(array_map('array_keys',$data),'array_merge',[]));
Or in a function:
function get_array_children_keys($data) {
return array_unique(
array_reduce(array_map('array_keys', $data), 'array_merge', [])
);
}
Now lets break this down with an example, here is some sample data:
[
['key1' => 0],
['key1' => 0, 'key2' => 0],
['key3' => 0]
]
Starting with the inner most function, we run array_map with the array_keys function:
array_map('array_keys', $data)
This gives us the keys of from all child arrays
[
['key1'],
['key1', 'key2'],
['key3']
]
Then we run the array_reduce on the data with the array_merge callback and an empty array as the initial value:
array_reduce(..., 'array_merge', []);
This converts our multiple arrays into 1 flat array:
[
'key1',
'key1',
'key2',
'key3'
]
Now we strip out our duplicates with array_unique:
array_unique(...)
And end up with all our keys:
[
'key1',
'key2',
'key3'
]
foreach($bigArray as $array){
foreach($array as $key=>$value){
echo $key;
}
}
That should do what you want.
What about something like this :
$your_keys = array_keys($your_array[0]);
Of course, this is considering all sub-arrays have the same keys ; in this case, you only need the keys of the first sub-array (no need to iterate over all first-level sub-arrays, I guess)
And, as a shortened / simplified example :
$your_array = array(
array(
'action' => 'A',
'id' => 1,
'base' => array('id' => 145),
),
array(
'action' => 'B',
'id' => 2,
'base' => array('id' => 145),
),
array(
'action' => 'C',
'id' => 3,
'base' => array('id' => 145),
)
);
$your_keys = array_keys($your_array[0]);
var_dump($your_keys);
Will get you :
array
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'base' (length=4)
You can the use implode to get the string you asked for :
echo implode(', ', $your_keys);
will get you :
action, id, base
ie, the list of the keys of the first sub-array.
function __getAll2Keys($array_val){
$result = array();
$firstKeys = array_keys($array_val);
for($i=0;$i<count($firstKeys);$i++){
$key = $firstKeys[$i];
$result = array_merge($result,array_keys($array_val[$key]));
}
return $result;
}
try this function. It will return as you want.
While #raise answers provides a shortcut, it fails with numeric keys. The following should resolve this:
$secondKeys=array_unique(call_user_func_array('array_merge', array_map('array_keys',$a)));
array_map('array_keys',$a) : Loop through while getting the keys
...'array_merge'... : Merge the keys array
array_unique(... : (optional) Get unique keys.
I hope it helps someone.
UPDATE:
Alternatively you can use
$secondKeys=array_unique(array_merge(...array_map('array_keys', $a)));
That provides same answer as above, and much faster.
My proposal, similar to this answer but faster and using spread operator (PHP 5.6+).
array_merge(...array_values($fields))
if you want move names to array values and reset keys to 0..n just use array_keys in last step.
array_keys(array_merge(...array_values($fields)))
Maybe you can use array_map function, which allows you to avoid array iteration and return an array with the keys you need as values.
will be like this
$newArray = array_map(function($value){return array_keys($value);},$yourArray);
var_dump($newArray);
array (size=2)
0 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'EBase' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
1 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'FType' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
With this function you can get all keys from a multidimensional array
function arrayKeys($array, &$keys = array()) {
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($value)) {
$this->arrayKeys($value, $keys);
}
}
return $keys;
}
Only if all records have the same keys you could do:
$firstItem = reset($array);
$keys = array_keys($firstItem);
Obviously, this is not the correct answer to this specific question, where the records have different keys. But this might be the question you find when looking how to retrieve second level keys from an array where all keys are the same (I did). If all the record have the same keys, you can simply use the first item in the array with reset() and get the keys from the first item with array_keys().

Categories