How to decode a JSON String with several objects in PHP? - php

I know how to decode a JSON string with one object with your help from this example How to decode a JSON String
But now I would like to improve decoding JSON string with several objects and I can't understand how to do it.
Here is an example:
{ "inbox": [
{ "firstName": "Brett", "lastName":"McLaughlin" },
{ "firstName": "Jason", "lastName":"Hunter" },
{ "firstName": "Elliotte", "lastName":"Harold" }
],
"sent": [
{ "firstName": "Isaac", "lastName": "Asimov" },
{ "firstName": "Tad", "lastName": "Williams" },
{ "firstName": "Frank", "lastName": "Peretti" }
],
"draft": [
{ "firstName": "Eric", "lastName": "Clapton" },
{ "firstName": "Sergei", "lastName": "Rachmaninoff" }
]
}
How to make just one foreach() to
decode above JSON string?
How to detect object's names: inbox,
sent or draft on this foreach()?

New answer
Re your revised question: foreach actually works with properties as well as with many-valued items (arrays), details here. So for instance, with the JSON string in your question:
$data = json_decode($json);
foreach ($data as $name => $value) {
// This will loop three times:
// $name = inbox
// $name = sent
// $name = draft
// ...with $value as the value of that property
}
Within your main loop over the properties, you can use an inner loop to go over the array entries each property points to. So for instance, if you know that each of the top-level properties has an array value, and that each array entry has a "firstName" property, this code:
$data = json_decode($json);
foreach ($data as $name => $value) {
echo $name . ':'
foreach ($value as $entry) {
echo ' ' . $entry->firstName;
}
}
...will show:
inbox:
Brett
Jason
Elliotte
sent:
Issac
Tad
Frank
draft:
Eric
Sergei
Old answer(s)
Begin edit
Re your comment:
Now I would like to know how to decode JSON string with several objects!
The example you posted does have several objects, they're just all contained within one wrapper object. This is a requirement of JSON; you cannot (for example) do this:
{"name": "I'm the first object"},
{"name": "I'm the second object"}
That JSON is not valid. There has to be a single top-level object. It might just contain an array:
{"objects": [
{"name": "I'm the first object"},
{"name": "I'm the second object"}
]}
...or of course you can give the individual objects names:
{
"obj0": {"name": "I'm the first object"},
"obj1": {"name": "I'm the second object"}
}
End edit
Your example is one object containing three properties, the value of each of which is an array of objects. In fact, it's not much different from the example in the question you linked (which also has an object with properties that have array values).
So:
$data = json_decode($json);
foreach ($data->programmers as $programmer) {
// ...use $programmer for something...
}
foreach ($data->authors as $author) {
// ...use $author for something...
}
foreach ($data->musicians as $musician) {
// ...use $musician for something...
}

You can use the json_decode function to decode the JSON string :
$json = <<<JSON
{ "programmers": [
{ "firstName": "Brett", "lastName":"McLaughlin" },
{ "firstName": "Jason", "lastName":"Hunter" },
{ "firstName": "Elliotte", "lastName":"Harold" }
],
"authors": [
{ "firstName": "Isaac", "lastName": "Asimov" },
{ "firstName": "Tad", "lastName": "Williams" },
{ "firstName": "Frank", "lastName": "Peretti" }
],
"musicians": [
{ "firstName": "Eric", "lastName": "Clapton" },
{ "firstName": "Sergei", "lastName": "Rachmaninoff" }
]
}
JSON;
$data = json_decode($json);
Then, to see what the data looks like, you can dump it :
var_dump($data);
And you'll see you have an object containing three arrays, each one containing other sub-objects :
object(stdClass)[1]
public 'programmers' =>
array
0 =>
object(stdClass)[2]
public 'firstName' => string 'Brett' (length=5)
public 'lastName' => string 'McLaughlin' (length=10)
1 =>
object(stdClass)[3]
public 'firstName' => string 'Jason' (length=5)
public 'lastName' => string 'Hunter' (length=6)
...
public 'authors' =>
array
0 =>
object(stdClass)[5]
public 'firstName' => string 'Isaac' (length=5)
public 'lastName' => string 'Asimov' (length=6)
...
Which means you know how to access your data.
For example, to display the list of the programmers, you could use :
foreach ($data->programmers as $programmer) {
echo $programmer->firstName . ' ' . $programmer->lastName . '<br />';
}
Which would get you the following output :
Brett McLaughlin
Jason Hunter
Elliotte Harold

Related

PHP convert similar names variables to json

I'm getting via url querystring variables like:
myserver_state=1&myserver_running=2&myserver_mem=3
Currently i'm adding to an existing json like:
{
"key1": "1",
"key2": "2",
"key3": "3",
"myserver_state": "1",
"myserver_running": "2",
"myserver_mem": "3"
}
And i really want it like this:
{
"key1": "1",
"key2": "2",
"key3": "3",
"myserver": {
"state": "1",
"running": "2",
"mem": "3"
}
}
I'm using this to load them:
$formdata = array(
'state'=> $_POST['state'],
'uassip'=> $_POST['uassip'],
'uassipport'=> $_POST['uassipport'],
'c_uacminrtpport'=> $_POST['c_uacminrtpport'],
'c_uacmaxrtpport'=> $_POST['c_uacmaxrtpport'],
'c_cps'=> $_POST['c_cps'],
'c_totalcalls'=> $_POST['c_totalcalls'],
'c_maxchannels'=> $_POST['c_maxchannels'],
'c_duration'=> $_POST['c_duration'],
'c_to'=> $_POST['c_to'],
'c_uacxml'=> $_POST['c_uacxml']
);
echo "fromdata: <br>"; echo var_dump($formdata) . "<br><hr>";
if(file_put_contents('testconfig.json', json_encode($formdata) )) echo 'OK';
else echo 'Unable to save data in "testconfig.json"';
Many thanks!
EDIT:
following comments i tried:
status.php?server1[current_state]=10
this actually works to:
"c_uacxml": "telnyx-uac-invite-ok.xml",
"server1": {
"current_state": "10"
}
}
Which is great, BUT, if i then want to add an element like this:
status.php?server1[current_mem]=1
This actually REPLACES the whole server1
"c_uacxml": "telnyx-uac-invite-ok.xml",
"server1": {
"current_mem": "10"
}
}
and i lose the already existing current_state
Just use multidimensional array within your URL like:
test.php?key1=1&key2=2&myserver[state]=1&myserver[running]=2&myserver[mem]=3
so easy script
<?php
echo '<pre>';
echo json_encode($_GET, JSON_PRETTY_PRINT);
will give you
{
"key1": "1",
"key2": "2",
"myserver": {
"state": "1",
"running": "2",
"mem": "3"
}
}
of course, if required you can use also POST request with the same naming rules.
in order to create a nested JSON object, you need to create an array within an array.
E.g.
$example = [
'key1' => 'foo',
'key2' => 'bar',
'key3' => [
'subkey1' => 'foo',
'subkey2' => 'bar',
],
];
When running it through json_encode(), it will result in
{
"key1": "foo",
"key2": "bar",
"key3": {
"subkey1": "foo",
"subkey2": "bar"
}
}
Also it's not necessary to load form data like this –
$formdata = [
'state' => $_POST['state'],
'uassip' => $_POST['uassip'],
'uassipport' => $_POST['uassipport'],
'c_uacminrtpport' => $_POST['c_uacminrtpport'],
'c_uacmaxrtpport' => $_POST['c_uacmaxrtpport'],
'c_cps' => $_POST['c_cps'],
'c_totalcalls' => $_POST['c_totalcalls'],
'c_maxchannels' => $_POST['c_maxchannels'],
'c_duration' => $_POST['c_duration'],
'c_to' => $_POST['c_to'],
'c_uacxml' => $_POST['c_uacxml'],
];
Since the $_POST already contains a structure that you are trying to recreate. You can simply assign the post data to a new varaible.
On another note, I highly recommend you to check out PSR PHP standards, they will greatly help to improve code readability and your code structure :) https://www.php-fig.org/psr/

auto-incrementing ID on my JSON array

I've been trying to do this for a while now and I just can't seem to get it right. One post got me very close but not quite there because my of JSON's hierarchy. (it's an assignment and this hierarchy is mandatory.)
What I do right now is submit info from one page, POST it to my php on another page, save it in an array there, json_encode that array and write that to my JSON file.
Here is my watered-down code, hopefully getting rid of most unnecessary code:
<?php
$filename = "json/exercises.json";
$filesize = filesize($filename);
$fp = fopen($filename, "r+");
#Accept the submitted form
$exLanguage = $_POST['exLanguage'];
$exTitle = $_POST['exTitle'];
$exStuff = $_POST['exStuff'];
#write to JSON with an incrementing ID
if (file_get_contents($filename) == "") {
$exercise = array (
"id" => 1,
"lang" => $exLanguage,
"title" => $exTitle,
"main_object" =>
[
"exStuff" => $exStuff
]
);
$exercise_json = json_encode($exercise, JSON_PRETTY_PRINT);
file_put_contents($filename, $exercise_json, FILE_APPEND);
} else {
#Get the last set ID
$jsonid = json_decode(fread($fp, $filesize), true);
$last = end($jsonid);
$title = prev($jsonid);
$lang = prev($jsonid);
$id = prev($jsonid);
$exercise = array (
"id" => ++$id,
"lang" => $exLanguage,
"title" => $exTitle,
"main_object" =>
[
"exStuff" => $exStuff
]
);
$exercise_json = json_encode($exercise, JSON_PRETTY_PRINT);
file_put_contents($filename, $exercise_json, FILE_APPEND);
}
?>
now what this does is if my json is empty it adds the first array correctly with the ID at 1. Then if I try to add to my json again it adds it correctly with the ID at 2. But any more attempted writes to the JSON will give me these errors:
Warning: end() expects parameter 1 to be array, null given
Warning: prev() expects parameter 1 to be array, null given
Warning: prev() expects parameter 1 to be array, null given
Warning: prev() expects parameter 1 to be array, null given
I tried doing a
$reset = reset($jsonid);
after writing to file but that didn't work, just gave me another error on the 3rd write for the reset being given a null too.
Can anyone please tell me how to get this too work? Or if there is a much easier way of getting this done?
Understand JSON format first. Its a collection of Objects which means attribute: value pair wrapped in {} and separated by comma , and then again wrapped in {} OR [] at top level.
Your JSON structure is incomplete or corrupted. What you are doing currently will create JSON in following format in your JSON file:
{ "id": 1, "lang": "as", "title": "asdsad" }
{ "id": 2, "lang": "as", "title": "asdsad" }
{ "id": 3, "lang": "as", "title": "asdsad" }
{ "id": 4, "lang": "as", "title": "asdsad" }
So json_decode will return null in this case because of invalid JSON format.
You need to keep appending your new JSON in existing JSON such that above format will become like this:
[
{ "id": 1, "lang": "as", "title": "asdsad" },
{ "id": 2, "lang": "as", "title": "asdsad" },
{ "id": 3, "lang": "as", "title": "asdsad" },
{ "id": 4, "lang": "as", "title": "asdsad" }
]
Which means your else block is incorrect. Use following code in else block:
$jsonid = json_decode(file_get_contents($filename), true);
$last = end($jsonid);
$id = $last['id'];
$jsonid[] = array (
"id" => ++$id,
"lang" => $exLanguage,
"title" => $exTitle,
"main_object" => array("exStuff" => $exStuff)
);
$exercise_json = json_encode($jsonid, JSON_PRETTY_PRINT);
file_put_contents($filename, $exercise_json, FILE_APPEND);
I hope you are not bound to use that incorrect/corrupted JSON format. That will not work with json_decode() in any case.

How to use an JSON return from a php query into an foreach loop?

i am using Codeigniter and inside a function i call a controller to return data which I want to use in an foreach to built an insert statement.
The JSON returned looks like this:
{
"Data": [
{
"id": "743",
"day": "1",
"day_type": "Party",
"day_dresscode": "Black",
"day_p_id": "1",
"description": "Test desc",
"name": "test"
},
{
"id": "743",
"day": "2",
"day_type": "Party",
"day_dresscode": "White",
"day_p_id": "1",
"description": "Test desc 1",
"name": "test 2"
}
]
}
my php looks like below:
// This where i got my JSON
$datavar = $this->model->get_json_data($id,$code);
// This is to decode the JSON
$datavar_decode['Data'] = json_decode($datavar,true);
Below is my foreach:
$i = 1;
foreach($datavar_decode['Data'] as $data):
$data_insert = array(
'val1' => $data['val1'],
'val2' => $data['val2'],
'val3' => $data['val3'],
'val4' => $data['val4']
);
$this->db->insert('mssqltable', $data_insert);
$i++;
endforeach;
It gives me below error:
Invalid argument supplied for foreach()
Don't use json.
You're problem is that you are returning an array of objects, and that's the behavior you get from $query->result() or if you use $query->row() then you get an object representing a single row.
In order to return an array, use $query->row_array() for a single row, or for multiple records returned you would use $query->result_array().
See all the details: https://www.codeigniter.com/user_guide/database/results.html
You can try this code to test that your $datavar_decode['Data'] doesn't allocate an empty array when you've got nothing to begin with anyway.
if (is_array($datavar_decode['Data']) || is_object($datavar_decode['Data']))
{
foreach ($datavar_decode['Data'] as $data)
{
...
}
}

How to decode multi-layers nested JSON String and display in PHP?

I know how to decode a JSON string and get the data from one dimensional array but how to get the data from the nested array?
Below is my code:
$data = json_decode($json);
and below is the JSON return value:
{
"area_metadata": [
{
"name": "A",
"label_location": {
"latitude": 1,
"longitude": 1
}
},
{
"name": "B",
"label_location": {
"latitude": 1,
"longitude": 1
}
}
],
"items": [
{
"update_timestamp": "2017-05-02T09:51:20+08:00",
"timestamp": "2017-05-02T09:31:00+08:00",
},
"locations": [
{
"area": "A",
"weather": "Showers"
},
{
"area": "B",
"weather": "Cloudy"
}
]
}
]}
I had tested:
echo $data->items->locations[0]->area;
but I got this error
Trying to get property of non-object
Also,I tried to convert JSON into array instead of object:
$data = json_decode($json,true);
if (isset($data))
{
foreach ($data->items->locations as $location)
{
if (empty($location["area"])) { continue; }
if ($location["area"] == "A")
{
echo $location["weather"];
}
}
}
but it also not working.
Could anyone can advise which step that I did wrongly?
Thanks!
Edited:
Below is the pastebin link with full JSON content.
https://pastebin.com/cewszSZD
The JSON you provided (in your question) is malformed and using json_decode() on it will result in NULL. Thus nothing will happen when you try to access the decoded object because it doesn't exist.
The full JSON you provided is valid and the reason why your code didn't yield any results is because in items there is an "inner"-array:
(...)
["items"] => array(1) {
[0] => array(4) {
// ^^^^^^^^^^^^^^^^^
["update_timestamp"] => string(25) "2017-05-02T09:21:18+08:00"
["timestamp"] => string(25) "2017-05-02T09:07:00+08:00"
["valid_period"] => array(2) {
["start"] => string(25) "2017-05-02T09:00:00+08:00"
["end"] => string(25) "2017-05-02T11:00:00+08:00"
}
["forecasts"] => array(47) {
[0] => array(2) {
["area"] => string(10) "Ang Mo Kio"
["forecast"] => string(19) "Partly Cloudy (Day)"
}
(...)
You'll have to access that array through key 0, for arrays it will look like this:
$data = json_decode($json, true);
echo $data['items'][0]['forecasts'][0]['area'];
// ^^^
And for objects like this:
$data = json_decode($json);
echo $data->items[0]->forecasts[0]->area;
// ^^^
The second 0 changes the location (the different arrays in the forecasts array).
You can check the output here (array approach) and here (object approach).
It would be easier to help if you post all the JSON data or link to a screenshot of it. Try:
$items[0]['locations'][0]['area'];
Single quotes on strings, no quotes on numbers.

PHP - JSON Data Parsing [duplicate]

This question already has an answer here:
How to extract and access data from JSON with PHP?
(1 answer)
Closed 11 months ago.
All,
I have the following JSON Data. I need help writing a function in PHP which takes a categoryid and returns all URLs belonging to it in an array.
Something like this::
<?php
function returnCategoryURLs(catId)
{
//Parse the JSON data here..
return URLArray;
}
?>
{
"jsondata": [
{
"categoryid": [
20
],
"url": "www.google.com"
},
{
"categoryid": [
20
],
"url": "www.yahoo.com"
},
{
"categoryid": [
30
],
"url": "www.cnn.com"
},
{
"categoryid": [
30
],
"url": "www.time.com"
},
{
"categoryid": [
5,
6,
30
],
"url": "www.microsoft.com"
},
{
"categoryid": [
30
],
"url": "www.freshmeat.com"
}
]
}
Thanks
What about something like this :
You first use json_decode, which is php's built-in function to decode JSON data :
$json = '{
...
}';
$data = json_decode($json);
Here, you can seen what PHP kind of data (i.e. objects, arrays, ...) the decoding of the JSON string gave you, using, for example :
var_dump($data);
And, then, you loop over the data items, searching in each element's categoryid if the $catId you are searching for is in the list -- in_array helps doing that :
$catId = 30;
$urls = array();
foreach ($data->jsondata as $d) {
if (in_array($catId, $d->categoryid)) {
$urls[] = $d->url;
}
}
And, each time you find a match, add the url to an array...
Which means that, at the end of the loop, you have the list of URLs :
var_dump($urls);
Gives you, in this example :
array
0 => string 'www.cnn.com' (length=11)
1 => string 'www.time.com' (length=12)
2 => string 'www.microsoft.com' (length=17)
3 => string 'www.freshmeat.com' (length=17)
Up to you to build from this -- there shouldn't be much left to do ;-)
Try the built-in json_decode function.

Categories