Processing a JSON response from TFL api using PHP? - php

I am trying to get certain information from the following JSON response from an API. This is the actual API call.
{
"$type": "Tfl.Api.Presentation.Entities.PlacesResponse, Tfl.Api.Presentation.Entities",
"centrePoint": [
51.555,
0.059
],
"places": [{
"$type": "Tfl.Api.Presentation.Entities.StopPoint, Tfl.Api.Presentation.Entities",
"naptanId": "490009219W",
"indicator": "Stop B",
"stopLetter": "B",
"modes": [
"bus"
],
"icsCode": "1009219",
"stopType": "NaptanPublicBusCoachTram",
"stationNaptan": "490G00009219",
"lines": [{
"$type": "Tfl.Api.Presentation.Entities.Identifier, Tfl.Api.Presentation.Entities",
"id": "25",
"name": "25",
"uri": "/Line/25",
"type": "Line"
}, {
"$type": "Tfl.Api.Presentation.Entities.Identifier, Tfl.Api.Presentation.Entities",
"id": "86",
"name": "86",
"uri": "/Line/86",
"type": "Line"
}, {
"$type": "Tfl.Api.Presentation.Entities.Identifier, Tfl.Api.Presentation.Entities",
"id": "w19",
"name": "W19",
"uri": "/Line/w19",
"type": "Line"
}],
"lineGroup": [{
"$type": "Tfl.Api.Presentation.Entities.LineGroup, Tfl.Api.Presentation.Entities",
"naptanIdReference": "490009219W",
"stationAtcoCode": "490G00009219",
"lineIdentifier": [
"25",
"86",
"w19"
]
}],
"lineModeGroups": [{
"$type": "Tfl.Api.Presentation.Entities.LineModeGroup, Tfl.Api.Presentation.Entities",
"modeName": "bus",
"lineIdentifier": [
"25",
"86",
"w19"
]
}],
"status": true,
"id": "490009219W",
"commonName": "Little Ilford Lane",
"distance": 64.10041498232529,
"placeType": "StopPoint",
"additionalProperties": [{
"$type": "Tfl.Api.Presentation.Entities.AdditionalProperties, Tfl.Api.Presentation.Entities",
"category": "Direction",
"key": "CompassPoint",
"sourceSystemKey": "Naptan490",
"value": "W"
}, {
"$type": "Tfl.Api.Presentation.Entities.AdditionalProperties, Tfl.Api.Presentation.Entities",
"category": "Direction",
"key": "Towards",
"sourceSystemKey": "CountDown",
"value": "East Ham or Manor Park"
}],
"lat": 51.554475,
"lon": 0.059381
}]
}
I want to get the naptanId, line identifier and towards as name value pairs and print them. For example,
naptan :490009219W;
lineidentifer Whatever the values are
towards : "Eastham or manor park"
Please help me I am a beginner,
Thank you in advance

Based on your question, it seems you are only interested in the values from the first place returned, so I'll assume that in the answer.
To get the data from the API into an object structure (as opposed to the JSON string you initially get):
$data = json_decode(file_get_contents('https://api.tfl.gov.uk/Place?lat=51.555504&lon=0.0592359&radius=200&includeChildren=False&type=NaptanPublicBusCoachTram&app_id=&app_key='), true);
To get the naptanId:
$naptanId = $data['places'][0]['naptanId'];
To get the lineIdentifier, which I'll assume is the one from the first lineGroup element (not lineModeGroups, but you can change as appropriate):
$lineIdentifier = $data['places'][0]['lineGroup'][0]['lineIdentifier'];
This value will be an array.
To get the towards value is a bit more complex, because you need to filter the additionalProperties array based on a child key, then pull out the value; again I'm assuming you're only interested in the first value:
$towards = array_values(array_filter(
$data['places'][0]['additionalProperties'],
function ($property) {
return $property['key'] === 'Towards';
}
))[0]['value'];
The call to array_filter pulls out the additionalProperties element where key === 'Towards' (note this assumes case sensitivity, you could add a strtolower and change the string literal to 'towards' if you want to match case insensitively). The call to array_values is necessary to normalise the array indexes. Then we pull out the first element [0] and get its value property.
Note that the above code does not do any error checking, for example if the API call does not return any places then the first time you do $data['places'][0] it will fail. If you need to handle these cases (which you almost certainly do), then you will need to pre-check these things, e.g.:
if (!isset($data['places']) || sizeof($data['places']) === 0) {...}

Related

how can two array marge each inside object key are matching it Cross?

I have two array user and game
$user =[
{
"name": "jone",
"id": "100"
},
{
"name": "Peters",
"id": "200"
}
]
$game = [
{
"name": "tennis",
"level": "05",
"user_id": "100"
},
{
"name": "football",
"level": "03",
"user_id": "100"
},
{
"name": "football",
"level": "05",
"user_id": "200"
}
]
I want to get a result like this using PHP / Laravel
$user = [
{
"name": "jone",
"id": "100"
"game": [
{
"name": "tennis",
"level": "05",
"user_id": "100"
},
{
"name": "football",
"level": "03",
"user_id": "100"
}
],
},
{
"name": "Peters",
"id": "200"
"game": [
{
"name": "football",
"level": "05",
"user_id": "200"
}
],
}
],
any one help me
I understand that I should not provide an answer to this "non-question". I still do so, as I think it might carry some learning value.
The idea is, not to cycle each game for each user (as the naive approach would be), as this simply doesn't scale. It is much better to use a matching array and then sort the games into it:
//Prepare matching array
$user_games=array();
foreach ($user as $u) {
$u['game']=array();
$user_games[$u['id']]=$u;
}
//Sort games into matching array
foreach ($game as $g) {
$user_games[$g['user_id']]['game'][]=$g;
}
This way a new game will not create n cycles (n being the number of users), but only one.
print_r($user_games);
creates the desired output. If the user IDs as indices are a problem, just use
print_r(array_values($user_games);

PHP json_encode string key as array

i write a api for my games to get achievements and so on. i load the data from a webserver into unity c# over a www request. i need a array from php which contain achievements and more data. the problem is, the result is this
[
{"ID":"1",
"gameID":"1",
"name":"achv1",
"neededvalue":"50",
"player_achievements":{
"ID":"8",
"achievementID":"1",
"playerID":"9",
"value":"",
"completed":""
}
},
{"ID":"2",
"gameID": "1",
"name":"achv2",
"neededvalue":"100",
"player_achievements":{
"ID":"9",
"achievementID":"2",
"playerID":"9",
"value":"","completed":""
}
}
]
the player_achievements is a child array of the head array and i need the square_brackets around the player_achievements [] because untity c# cannot convert it to an object. i search hours for finding a solution but nobody explain how. i found this link but this is not a option for me. i want the string keys and not numbers. give it a way to use the string keys as array and not as object ?
i need it like so:
[
{ "ID":"1",
"gameID":"1",
"name":"achv1",
"neededvalue":"50",
"player_achievements":[
{ "ID":"8",
"achievementID":"1",
"playerID":"9",
"value":"",
"completed":""
}
]
},
{
"ID":"2",
"gameID":"1",
"name":"achv2",
"neededvalue":"100",
"player_achievements":[
{ "ID":"9",
"achievementID":"2",
"playerID":"9",
"value":"",
"completed":""
}
]
}
]
If I am reading your question correctly, you need to make the player_achievements element an array containing the original value of that element.
<?php
$json = <<<END
[
{"ID":"1",
"gameID":"1",
"name":"achv1",
"neededvalue":"50",
"player_achievements":{
"ID":"8",
"achievementID":"1",
"playerID":"9",
"value":"",
"completed":""
}
},
{"ID":"2",
"gameID": "1",
"name":"achv2",
"neededvalue":"100",
"player_achievements":{
"ID":"9",
"achievementID":"2",
"playerID":"9",
"value":"","completed":""
}
}
]
END;
$data = json_decode($json, true);
for($i=0;$i<sizeof($data);$i++)
{
$data[$i]['player_achievements'] = [$data[$i]['player_achievements']];
}
echo json_encode($data);
This produces a structure like the one you say you need.
[
{
"ID": "1",
"gameID": "1",
"name": "achv1",
"neededvalue": "50",
"player_achievements": [
{
"ID": "8",
"achievementID": "1",
"playerID": "9",
"value": "",
"completed": ""
}
]
},
{
"ID": "2",
"gameID": "1",
"name": "achv2",
"neededvalue": "100",
"player_achievements": [
{
"ID": "9",
"achievementID": "2",
"playerID": "9",
"value": "",
"completed": ""
}
]
}
]
I found an answer, I add a zero before the child element as key of array.

Remove instance of square brackets, if found two successive instances

I have a data in following manner:
{"id": "sugarcrm", "text": "sugarcrm", "children": [ [ { "id": "accounts", "text": "accounts", "children": [ { "id": "id", "text": "id" }, { "id": "name", "text": "name" } ] } ] ] }
Now, I want to remove the instance of square bracket i.e. [ and ] if there are two successive instances like this [ [ or ] ].
Now if you see the above data, you'll get to see that there are instances of [ and ] which are repeated twice successively. So I want to remove one instance of each.
Now, I can check the two successively repeated instances of each and remove one, like this
$text = '{"id": "sugarcrm", "text": "sugarcrm", "children": [ [ { "id": "accounts", "text": "accounts", "children": [ { "id": "id", "text": "id" }, { "id": "name", "text": "name" } ] } ] ] }';
echo preg_replace('/\[ \[+/', '[', $text);
Now, the above code is for [. So to remove the successively repeated instance of ], I'll have to repeat the same code again.
I want to know, is there a better way to achieve the same result or not. Meanwhile, I can work it out, but still what if, in future, I'll have to do the same for any other character? Kindly guide me here.
You are processing a json string. It is contraindicated to attempt string manipulations (with regex or other) because there are very possible pitfalls with "over-matching".
While I don't fully understand the variability of your data structure, I can provide some temporary guidance by converting your json string to an array and then safely modifying the data with an array function.
Consider this:
Code: (Demo)
$json='{"id": "sugarcrm", "text": "sugarcrm", "children": [ [ { "id": "accounts", "text": "accounts", "children": [ { "id": "id", "text": "id" }, { "id": "name", "text": "name" } ] } ] ] }';
$array=json_decode($json,true); // convert to array
foreach($array as &$a){ // $a is modifiable by reference
if(is_array($a) && isset($a[0]) && isset($a[0][0])){ // check if array and if two consecutive/nested indexed subarrays
$a=array_column($a,0); // effectively shift deeper subarray up one level
}
}
$json=json_encode($array);
echo $json;
Output:
{"id":"sugarcrm","text":"sugarcrm","children":[{"id":"accounts","text":"accounts","children":[{"id":"id","text":"id"},{"id":"name","text":"name"}]}]}
For that matter, if you know where the double-nested-indexes are, then you can access them without looping (or modifying by reference) like this:
$json='{"id": "sugarcrm", "text": "sugarcrm", "children": [ [ { "id": "accounts", "text": "accounts", "children": [ { "id": "id", "text": "id" }, { "id": "name", "text": "name" } ] } ] ] }';
$array=json_decode($json,true);
$array['children']=array_column($array['children'],0); // modify 2 known, nested, indexed subarrays
$json=json_encode($array);
echo $json;
How about:
echo str_replace(array('[ [', '] ]'), array('[', ']'), $text);

Parsing a JSON file with multiple levels in a MySQL database

I've some trouble with parsing a JSON file into a MySQL database. It's an export of some Facebookstats.
Because I've multiple export of multiple pages, it's important that I've the corresponding ID in the database.
The JSONfile (or cURL from Facebook) looks like this:
{
"data": [
{
"name": "impressions",
"period": "week",
"values": [
{
"value": 123456789,
"end_time": "2016-01-01T08:00:00+0000"
},
{
"value": 12345678,
"end_time": "2016-01-02T08:00:00+0000"
},
{
"value": 1234567,
"end_time": "2016-01-03T08:00:00+0000"
},
{
"value": 123456,
"end_time": "2016-01-04T08:00:00+0000"
},
{
"value": 12345,
"end_time": "2016-01-05T08:00:00+0000"
}
],
"title": "Weekly Impressions",
"description": "The number of impressions seen of any content associated with your Page. (Total Count)",
"id": "101010101010\/insights\/page_impressions\/week"
}
],
"paging": {
"previous": "1",
"next": "2"
}
}
I would, ideally, parse this data into a MySQL database that looks like this:
id value end_time
101010101010 123456789 2016-01-01T08:00:00+0000
101010101010 12345678 2016-01-02T08:00:00+0000
101010101010 1234567 2016-01-03T08:00:00+0000
101010101010 123456 2016-01-04T08:00:00+0000
101010101010 12345 2016-01-05T08:00:00+0000
I hope someone had some ideas :-)
Use json_decode(). Example:
$jsonString = '{
"data": [
{
"name": "impressions",
"period": "week",
"values": [
{
"value": 123456789,
"end_time": "2016-01-01T08:00:00+0000"
},
{
"value": 12345678,
"end_time": "2016-01-02T08:00:00+0000"
},
{
"value": 1234567,
"end_time": "2016-01-03T08:00:00+0000"
},
{
"value": 123456,
"end_time": "2016-01-04T08:00:00+0000"
},
{
"value": 12345,
"end_time": "2016-01-05T08:00:00+0000"
}
],
"title": "Weekly Impressions",
"description": "The number of impressions seen of any content associated with your Page. (Total Count)",
"id": "101010101010\/insights\/page_impressions\/week"
}
],
"paging": {
"previous": "1",
"next": "2"
}
}';
Then decode it to an associative array:
$assocData = json_decode($jsonString, true); //Setting second optional parameter to true makes it return an associative array.
Then access it however you want:
$data = $assocData['data'];

fetch values from array within an array

I have a multidimensional array, i wish to extract each value from this array.
The array is stored in $data.
{"success":true,"categories":
[
{"
category_id":"C1",
"parent_id":"P1",
"name":"N1",
"categories":
[
{
"category_id":"C11",
"parent_id":"P11",
"name":"N11",
},
{
"category_id":"C12",
"parent_id":"P12",
"name":"N12",
},
],
"status":"1"
},
{
category_id":"C2",
"parent_id":"P2",
"name":"N2",
"categories":
[
{
"category_id":"C21",
"parent_id":"P21",
"name":"N21",
[
{
"category_id":"C22",
"parent_id":"P23",
"name":"N24",
}
],
"status":"2"
}
],
"status":"3"
},
]
}
I tried using
$total = $data['categories']['category_id'];
to fetch value C11
but wasn't able to do so.
can anyone tell how i can fetch all the data especially C22
You have to first use json_decode.
$array = json_decode($data, true);
Then you can access the array as you have stated.
Or loop throught the categories:
if (!empty($array)) {
foreach ($array['categories'] as $category) {
echo $category['id'];
}
}
You may have to do this recursively to loop through the categories within the categories. But it depends completely what you want to achieve. A nested loop could do the job if it is always just one level deep.
EDIT
The JSON you have provided is not quite right, I have given a corrected one below:
{
"success": true,
"categories": [
{
"category_id": "C1",
"parent_id": "P1",
"name": "N1",
"categories": [
{
"category_id": "C11",
"parent_id": "P11",
"name": "N11"
},
{
"category_id": "C12",
"parent_id": "P12",
"name": "N12"
}
],
"status": "1"
},
{
"category_id": "C2",
"parent_id": "P2",
"name": "N2",
"categories": [
{
"category_id": "C21",
"parent_id": "P21",
"name": "N21",
"categories": [
{
"category_id": "C22",
"parent_id": "P23",
"name": "N24"
}
],
"status": "2"
}
],
"status": "3"
}
]
}
There were a few trailing commas and missing quote marks.
The data is not in PHP array, its a JSON array. You have to decode it, by using json_decode() function.
That's JSON, not php multidimensional array. You can use json_decode function to read through it.

Categories