How to process JSON in PHP?
If you call json_decode($data,true);
, your data will be:
Array(
"Product"=>Array(
Array(
"Product_Title"=>"Cloth",
"Product_Description"=>"Here is cloth",
"Price"=>"100",
"Category_ID"=>"1"
),
Array(
.............
)
)
);
What is wrong with that?
How to extract and access data from JSON with PHP?
Intro
First off you have a string. JSON is not an array, an object, or a data structure. JSON is a text-based serialization format - so a fancy string, but still just a string. Decode it in PHP by using json_decode()
.
$data = json_decode($json);
Therein you might find:
- scalars: strings, ints, floats, and bools
- nulls (a special type of its own)
- compound types: objects and arrays.
These are the things that can be encoded in JSON. Or more accurately, these are PHP's versions of the things that can be encoded in JSON.
There's nothing special about them. They are not "JSON objects" or "JSON arrays." You've decoded the JSON - you now have basic everyday PHP types.
Objects will be instances of stdClass, a built-in class which is just a generic thing that's not important here.
Accessing object properties
You access the properties of one of these objects the same way you would for the public non-static properties of any other object, e.g. $object->property
.
$json = '
{
"type": "donut",
"name": "Cake"
}';
$yummy = json_decode($json);
echo $yummy->type; //donut
Accessing array elements
You access the elements of one of these arrays the same way you would for any other array, e.g. $array[0]
.
$json = '
[
"Glazed",
"Chocolate with Sprinkles",
"Maple"
]';
$toppings = json_decode($json);
echo $toppings[1]; //Chocolate with Sprinkles
Iterate over it with foreach
.
foreach ($toppings as $topping) {
echo $topping, "\n";
}
Glazed
Chocolate with Sprinkles
Maple
Or mess about with any of the bazillion built-in array functions.
Accessing nested items
The properties of objects and the elements of arrays might be more objects and/or arrays - you can simply continue to access their properties and members as usual, e.g. $object->array[0]->etc
.
$json = '
{
"type": "donut",
"name": "Cake",
"toppings": [
{ "id": "5002", "type": "Glazed" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5004", "type": "Maple" }
]
}';
$yummy = json_decode($json);
echo $yummy->toppings[2]->id; //5004
Passing true
as the second argument to json_decode()
When you do this, instead of objects you'll get associative arrays - arrays with strings for keys. Again you access the elements thereof as usual, e.g. $array['key']
.
$json = '
{
"type": "donut",
"name": "Cake",
"toppings": [
{ "id": "5002", "type": "Glazed" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5004", "type": "Maple" }
]
}';
$yummy = json_decode($json, true);
echo $yummy['toppings'][2]['type']; //Maple
Accessing associative array items
When decoding a JSON object to an associative PHP array, you can iterate both keys and values using the foreach (array_expression as $key => $value)
syntax, eg
$json = '
{
"foo": "foo value",
"bar": "bar value",
"baz": "baz value"
}';
$assoc = json_decode($json, true);
foreach ($assoc as $key => $value) {
echo "The value of key '$key' is '$value'", PHP_EOL;
}
Prints
The value of key 'foo' is 'foo value'
The value of key 'bar' is 'bar value'
The value of key 'baz' is 'baz value'
Don't know how the data is structured
Read the documentation for whatever it is you're getting the JSON from.
Look at the JSON - where you see curly brackets {}
expect an object, where you see square brackets []
expect an array.
Hit the decoded data with a print_r()
:
$json = '
{
"type": "donut",
"name": "Cake",
"toppings": [
{ "id": "5002", "type": "Glazed" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5004", "type": "Maple" }
]
}';
$yummy = json_decode($json);
print_r($yummy);
and check the output:
stdClass Object
(
[type] => donut
[name] => Cake
[toppings] => Array
(
[0] => stdClass Object
(
[id] => 5002
[type] => Glazed
)
[1] => stdClass Object
(
[id] => 5006
[type] => Chocolate with Sprinkles
)
[2] => stdClass Object
(
[id] => 5004
[type] => Maple
)
)
)
It'll tell you where you have objects, where you have arrays, along with the names and values of their members.
If you can only get so far into it before you get lost - go that far and hit that with print_r()
:
print_r($yummy->toppings[0]);
stdClass Object
(
[id] => 5002
[type] => Glazed
)
Take a look at it in this handy interactive JSON explorer.
Break the problem down into pieces that are easier to wrap your head around.
json_decode()
returns null
This happens because either:
- The JSON consists entirely of just that,
null
. - The JSON is invalid - check the result of
json_last_error_msg
or put it through something like JSONLint. - It contains elements nested more than 512 levels deep. This default max depth can be overridden by passing an integer as the third argument to
json_decode()
.
If you need to change the max depth you're probably solving the wrong problem. Find out why you're getting such deeply nested data (e.g. the service you're querying that's generating the JSON has a bug) and get that to not happen.
Object property name contains a special character
Sometimes you'll have an object property name that contains something like a hyphen -
or at sign @
which can't be used in a literal identifier. Instead you can use a string literal within curly braces to address it.
$json = '{"@attributes":{"answer":42}}';
$thing = json_decode($json);
echo $thing->{'@attributes'}->answer; //42
If you have an integer as property see: How to access object properties with names like integers? as reference.
Someone put JSON in your JSON
It's ridiculous but it happens - there's JSON encoded as a string within your JSON. Decode, access the string as usual, decode that, and eventually get to what you need.
$json = '
{
"type": "donut",
"name": "Cake",
"toppings": "[{ \"type\": \"Glazed\" }, { \"type\": \"Maple\" }]"
}';
$yummy = json_decode($json);
$toppings = json_decode($yummy->toppings);
echo $toppings[0]->type; //Glazed
Data doesn't fit in memory
If your JSON is too large for json_decode()
to handle at once things start to get tricky. See:
- Processing large JSON files in PHP
- How to properly iterate through a big json file
How to sort it
See: Reference: all basic ways to sort arrays and data in PHP.
How can I parse a JSON file with PHP?
To iterate over a multidimensional array, you can use RecursiveArrayIterator
$jsonIterator = new RecursiveIteratorIterator(
new RecursiveArrayIterator(json_decode($json, TRUE)),
RecursiveIteratorIterator::SELF_FIRST);
foreach ($jsonIterator as $key => $val) {
if(is_array($val)) {
echo "$key:\n";
} else {
echo "$key => $val\n";
}
}
Output:
John:
status => Wait
Jennifer:
status => Active
James:
status => Active
age => 56
count => 10
progress => 0.0029857
bad => 0
run on codepad
Parsing JSON with PHP
Your JSON is a mix of arrays and objects. So array notation will not work for all items.
For example, to find the brand use:
foreach ($json->items as $item) {
var_dump($item->product->brand);
}
Codepad example
JSON specification
How to parse JSON and access results
If your $result
variable is a string json like, you must use json_decode
function to parse it as an object or array:
$result = '{"Cancelled":false,"MessageID":"402f481b-c420-481f-b129-7b2d8ce7cf0a","Queued":false,"SMSError":2,"SMSIncomingMessages":null,"Sent":false,"SentDateTime":"\/Date(-62135578800000-0500)\/"}';
$json = json_decode($result, true);
print_r($json);
OUTPUT
Array
(
[Cancelled] =>
[MessageID] => 402f481b-c420-481f-b129-7b2d8ce7cf0a
[Queued] =>
[SMSError] => 2
[SMSIncomingMessages] =>
[Sent] =>
[SentDateTime] => /Date(-62135578800000-0500)/
)
Now you can work with $json
variable as an array:
echo $json['MessageID'];
echo $json['SMSError'];
// other stuff
References:
- json_decode - PHP Manual
parse json with php 5 not working
<?php
$jsonData = '{ "user":"John", "age":22, "country":"United States" }';
$phpArray = json_decode($jsonData);
print_r($phpArray);
foreach ($phpArray as $key => $value) {
echo "<p>$key | $value</p>";
}
?>
In PHP is there an elegant way to process JSON with deeply nested, optional nodes?
Well, I gotta be honest as that result of your method is just an array with two indexes, where word
is always the same and the definition
is different. If you really want $r->word
stored with that definition
than there is little that can be done.
However, you can shorten your isset()
code with:
- tanery operator with PHP version < 7
- null coalesce operator with PHP >= 7.
And example for both versions:
// PHP < 7.
foreach(isset($data['results']) ? $data['results'] : [] as $value){}
// PHP > 7
foreach($data['results'] ?? [] as $value){}
However, this is all just to suppress the error reporting, you can temporarily turn it off and back on again and just assume the index exist and forget about the isset()
.
I've defined the data like so:
$json = file_get_contents('data.json');
$data = json_decode($json, true);
As I prefer arrays over objects in this occasion, and a copy of your method of doing things with the PHP 7 null coalesce operator:
foreach($data['results'] ?? [] as $r){
foreach($r['lexicalEntries'] ?? [] as $l){
foreach($l['entries'] ?? [] as $e){
foreach($e['senses'] ?? [] as $s){
foreach( $s['definitions'] ?? [] as $d){
$list[] = [
'word' => $r['word'],
'definition' => $d
];
}
foreach($s['subsenses'] ?? [] as $ss){
foreach( $ss['definitions'] ?? [] as $d){
$list[] = [
'word' => $r['word'],
'definition' => $d
];
}
}
}
}
}
}
print_r($list);
However, there are other ways you can do this and that is to flatten the array. There are multiple ways you can do this, I prefer a generator however recursive generators are introduced in PHP 7 and above.
// This is a generator function, it flattens the entire given array.
// It yields an array containing the key and value on each iteration.
function array_walk_generator($array){
foreach($array as $k => $v){
yield $k => $v;
if(is_array($v)){
yield from array_walk_generator($v);
}
}
}
foreach($data['results'] as $result){
$list = [];
foreach(array_walk_generator($result) as $k => $v){
if($k == 'definitions' && is_array($v)){
$list[] = $v[0];
}
}
$return[] = [
'word' => $result['word'],
'definitions' => array_values(array_filter($list))
];
}
print_r($return);
This way you have in my opinion a better organized array, and this way it doesn't really care how the definitions are formatted.
Related Topics
How to Get Beanstalkd Queue to Work for PHP
How to Make Number_Format() Not to Round Numbers Up
Call to a Member Function Fetch() on Boolean
Setting Environment Variables for Accessing in PHP When Using Apache
Get Week Number (In the Year) from a Date PHP
Utf-8 Safe Equivalent of Ord or Charcodeat() in PHP
Google Gcm Server Returns Unauthorized Error 401
Codeigniter Cron Job Not Working
PHP Array_Filter with Arguments
How to Check If There Is a There Is a Wget Instance Running
PHP Commands Out of Sync Error
Google_Service_Directory - (403) Not Authorized to Access This Resource/Api
Laravel Stylesheets and JavaScript Don't Load for Non-Base Routes
Split Camelcase Word into Words with PHP Preg_Match (Regular Expression)
Add Extra Meta for Orders in Woocommerce