I have a json file stored on server & it looks like below:
{
"support_link":"#",
"support_link_2":"#",
"packs":[
{
"identifier":1,
"viewCount":0,
"downloadCount":0
},
{
"identifier":2,
"viewCount":0,
"downloadCount":0
}
]
}
By using PHP, I want to update the viewCount & downloadCount of some of the arrays inside packs.
But the thing is the data is received via a POST method to the server which contains another json with info. of which identifier to update & what param to update, & I am not able to update the existing file & save it back.
Received Json format:
{
"impressions": [
{
"identifier": "1",
"impressionCount": 2
},
{
"identifier": "100",
"impressionCount": 2
},
{
"identifier": "1000",
"impressionCount": 2000
}
],
"downloads": [
{
"identifier": "1",
"downloadCount": 10
}
]
}
What I've tried to do so far:
$json = file_get_contents('php://input');
if ($json != '') {
$properJsonFormatted = json_decode($json, true);
$impressions = $properJsonFormatted['impressions'];
$downloads = $properJsonFormatted['downloads'];
$testConfig =
$json = file_get_contents('php://input');
if ($json != '') {
$properJsonFormatted = json_decode($json, true);
$impressions = $properJsonFormatted['impressions'];
$downloads = $properJsonFormatted['downloads'];
$testConfig = json_decode(file_get_contents("test_config.json"),true);
$packs = $testConfig['packs'];
foreach ($packs as &$pack) {
$packIdentifier = $pack['identifier'];
foreach ($impressions as $impression) {
$impressionIdentifier = $impression['identifier'];
if ($packIdentifier == $impressionIdentifier) {
$pack['viewCount'] += $impression['impressionCount'];
$newCount = $pack['viewCount'];
print("Id: $packIdentifier, ViewCount: $newCount\n");
}
}
}
put_file_contents("test_config.json" , $testConfig);
// print_r($testConfig);
// Save back the updated test_config.json
}
}
UPDATE
Seem to have misinterpreted the question. The actual problem seems to be much simpler.
Change this:
put_file_contents("test_config.json" , $testConfig);
To this:
file_put_contents('test_config.json', json_encode($testConfig));
Also change this:
$packs = $testConfig['packs'];
To this:
$packs = &$testConfig['packs'];
As it seems you forgot to assign that by reference, while you correctly did that in the foreach.
So basically I want to parse a JSON file in PHP and insert the data into specific tables/columns. At the moment I have a working script but requires me to modify the JSON largely until it works. However, it won't end up working because the JSON data I'm collecting can vary in size having more data rows.
The JSON file is structured differently to most I have seen. Maybe because its output data from sensor units. I want to insert the data and the serial number into the data table, and have an error_log table where I can store the serial number and error messages as strings. How can I achieve this?
JSON File:
{
"device": {
"sn": 5165654,
"name": "FDI_AWS_DEMO",
"v": "2.7B3"
},
"channels": [
{
"code": "RH",
"name": "Relative Humidity",
"unit": "%"
},
{
"code": "AT",
"name": "Air Temperature",
"unit": "C"
},
{
"code": "MINVi",
"name": "Min voltage",
"unit": "V"
},
{
"code": "PTi",
"name": "Processor temperature",
"unit": "C"
},
{
"code": "SDB",
"name": "Network signal dB",
"unit": "dB"
},
{
"code": "LWS",
"name": "Leaf Wetness",
"unit": "%"
},
{
"code": "WSAV",
"name": "Wind Speed Avg",
"unit": "km/h"
},
{
"code": "WSMX",
"name": "Wind Speed Max",
"unit": "km/h"
},
{
"code": "WSMN",
"name": "Wind Speed Min",
"unit": "km/h"
},
{
"code": "PR_TOT",
"name": "PR Tot",
"unit": "mm"
},
{
"code": "RAIN",
"name": "Rain",
"unit": "mm"
},
{
"code": "FDI",
"name": "fdi",
"unit": "Unit"
},
{
"code": "DT",
"name": "Delta-T",
"unit": "C"
},
{
"code": "LAT",
"name": "Latitude",
"unit": "deg"
},
{
"code": "LON",
"name": "Longitude",
"unit": "deg"
},
{
"code": "WD",
"name": "Wind Direction",
"unit": "Degrees"
},
{
"code": "P1",
"name": "Par1",
"unit": ""
},
{
"code": "AVGCi",
"name": "Average Current",
"unit": "mA"
},
{}
],
"data": [
{
"$ts": 170801164400,
"$msg": "SD_FAIL;1"
},
{
"$ts": 170801170000,
"$msg": "WDT;WV01"
},
{
"$ts": 170801170000,
"$msg": "WDT;SDI12"
},
{
"$ts": 170801170000,
"$msg": "WDT;LWS"
},
{
"$ts": 170801170000,
"RH": 67.15,
"AT": 12.87,
"MINVi": 3.81,
"PTi": 23.4,
"LWS": "0*T",
"WSAV": 0,
"WSMX": 0,
"WSMN": 0,
"PR_TOT": 156,
"RAIN": 0,
"FDI": 0.239,
"DT": 2.881,
"WD": "0*T",
"P1": "0*T",
"AVGCi": 175
},
{}
]
}
PHP Code:
<?php
//connect to mysql db
$myConnection= mysqli_connect("localhost","root","******", "ii") or die ("could not connect to mysql");
//read the json file contents
$jsondata = file_get_contents('test.json');
//convert json object to php associative array
$data = json_decode($jsondata, true);
$id = $data['device']['sn'];
$ts = $data['data']['$ts'];
$RH = $data['data']['RH'];
$AT = $data['data']['AT'];
$MINVi = $data['data']['MINVi'];
$PTi = $data['data']['PTi'];
$SDB = $data['data']['SDB'];
$LWS = $data['data']['LWS'];
$WSAV = $data['data']['WSAV'];
$WSMX = $data['data']['WSMX'];
$WSMN = $data['data']['WSMN'];
$PR_TOT = $data['data']['PR_TOT'];
$RAIN = $data['data']['RAIN'];
$FDI = $data['data']['FDI'];
$DT = $data['data']['DT'];
$LAT = $data['data']['LAT'];
$LON = $data['data']['LON'];
$WD = $data['data']['WD'];
$P1 = $data['data']['P1'];
$AVGCi = $data['data']['AVGCi'];
//insert into mysql table
$sql = "INSERT INTO test(sn, date, RH, AT, MINVi, PTi, SDB, LWS, WSAV, WSMX, WSMN, PR_TOT, RAIN, FDI, DT, LAT, LON, WD, P1, AVGCi)
VALUES('$id', '$ts', '$RH','$AT', '$MINVi', '$PTi', '$SDB', '$LWS', '$WSAV', '$WSMX', '$WSMN', '$PR_TOT', '$RAIN', '$FDI', '$DT', '$LAT', '$LON', '$WD', '$P1', '$AVGCi')";
$query=mysqli_query($myConnection, $sql) or die(mysqli_error($myConnection));
?>
Tables Test data table and error_log table
JSON array var_dump - JSON var dump
Any help would be great
(After i get the general gist i want to incorporate PDO)
Do not convert json to associative array blindly. It creates more problems.
For accessing properties containing special characters or reserved
words use placeholders like $data->{'$ts'}
Loop through arrays and objects if needed.
Adding an auto increment id column to tables helps to store data
for one device.
It is a good idea to add time to error_log table as well
Tested bellow short version of your original question and it works.
<?php
$_user = 'root';
$_password= 'root';
$_db = 'localtest';
$_host = 'localhost';
$_port = 3306;
$con = new mysqli($_host, $_user, $_password, $_db) or die(mysql_error);
//read the json file contents
$jsondata = file_get_contents('test.json');
//do not convert to array
$json = json_decode($jsondata);
$id = $json->device->sn;
foreach($json->data as $key => $data){
if(empty($data) || !isset($data->{'$ts'})){
continue;
}
if (isset($data->{'$msg'})){
$msg = $data->{'$msg'};
$time = $data->{'$ts'};
$sql="INSERT into error_log (sn, time, MSG) VALUES (?,?,?); ";
$stmt = $con-> prepare($sql);
$stmt -> bind_param("iss", $id,$time, $msg);
$stmt -> execute();
}else{
$time = (isset($data->{'$ts'}))? $data->{'$ts'}:'';
$RH = (isset($data->RH))? $data->RH:'';
$AT = (isset($data->AT))? $data->AT:'';
$MINVi = (isset($data->MINVi))? $data->MINVi:'';
//insert into mysql table
$sql="INSERT into test (sn, date, RH, AT, MINVi) VALUES (?,?,?,?,?); ";
$stmt = $con-> prepare($sql);
$stmt -> bind_param("issss", $id,$time,$RH,$AT,$MINVi);
$stmt -> execute();
}
}
mysqli_close($con);
?>
looks like the json decode is turning the array into one that is object based...run the $data through the function below to turn it into more of a relational array that is setup the way you are trying to read it....
I cannot find the function i had for this at the moment but If you read the array more like this:
$newvar = $data->node;
//to echo this try this...
echo '<pre style="text-align:left;">';
print_r($data);
echo '</pre>';
OR try fb logs for php to see the arrays in console of ya browser - use firephp for the addon.
it should work just fine...
Hope that helps.
Consider building dynamic SQL calls conditionally depending on the error output. The array keys create the columns in INSERT clause and array values are quote wrapped in VALUES clause. Below echoes the sql statements just to demonstrate.
This should work for any change to JSON suffice no other new keys are added. Also, the array_splice is used to remove the $ts value the second time since you pass it in date column.
$jsondata = file_get_contents('Input.json');
$data = json_decode($jsondata, true);
$id = $data['device']['sn'];
foreach ($data['data'] as $k=>$v){
if (array_key_exists("\$msg",$v) & !empty($v)){
$sql = "INSERT INTO error_log (sn, msg)"
." VALUES('$id', '". $v["\$msg"] ."')";
echo $sql."\n";
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'SD_FAIL;1')
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;WV01')
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;SDI12')
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;LWS')
$query = mysqli_query(...);
}
if (!array_key_exists("\$msg",$v) & !empty($v)) {
$keysArray = array_keys($v);
$keysArray = array_splice($keysArray, 1);
$vVals = array_splice($v, 1);
$sql = "INSERT INTO test(sn, date, ". implode(", ", $keysArray) .")\n"
." VALUES('$id', '". $v['$ts'] ."',". implode("', '", $vVals) .")";
echo $sql."\n";
// INSERT INTO test(sn, date, RH, AT, MINVi, PTi, LWS, WSAV, WSMX, WSMN,
// PR_TOT, RAIN, FDI, DT, WD, P1, AVGCi)
// VALUES('5165654', '170801170000',67.15', '12.87', '3.81', '23.4', '0*T',
// '0', '0', '0', '156', '0', '0.239', '2.881', '0*T', '0*T', '175)
$query=mysqli_query(...)
}
}
Maybe something like this can get you on track... One thing I did notice is there doesn't appear to be an SDB entry in the given JSON data (FYI).
<?php
//connect to mysql db
$myConnection= mysqli_connect("localhost","root","******", "ii") or die ("could not connect to mysql");
//read the json file contents
$jsondata = file_get_contents('test.json');
//convert json object to php associative array
$data = json_decode($jsondata, true);
// Make sure $data has values
if (empty($data)) {
// Process error here
}
else {
// Make sure the proper keys have been set
if (!(isset($data['device']) && !empty($data['device']) && isset($data['data']) && !empty($data['data']))) {
// Process error here if not set
}
// If so, make sure the sn key has been set
elseif (!isset($data['device']['sn']) || empty($data['device']['sn'])) {
// Process error here if not set
}
else {
$data_arr = $data['data'];
foreach ($data_arr as $key => $arr) {
// Iterate through for loop
for ($i = 0; $i < count($data_arr); $i++) {
// Make sure every single key is set
if (!(isset($data_arr[$i]['$ts']) && isset($data_arr[$i]['RH']) && isset($data_arr[$i]['AT']) && isset($data_arr[$i]['MINVi']) && isset($data_arr[$i]['PTi']) && isset($data_arr[$i]['SDB']) && isset($data_arr[$i]['LWS']) && isset($data_arr[$i]['WSAV']) && isset($data_arr[$i]['WSMX']) && isset($data_arr[$i]['WSMN']) && isset($data_arr[$i]['PR_TOT']) && isset($data_arr[$i]['RAIN']) && isset($data_arr[$i]['FDI']) && isset($data_arr[$i]['DT']) && isset($data_arr[$i]['LAT']) && isset($data_arr[$i]['LON']) && isset($data_arr[$i]['WD']) && isset($data_arr[$i]['P1']) && isset($data_arr[$i]['AVGCi']) && isset($data_arr[$i]['DT']) && isset($data_arr[$i]['DT']))) {
// Process error here if not set
}
else {
// If all is well, perform the query
$id[$key][$i] = $arr['device']['sn'];
$ts[$key][$i] = $data_arr[$i]['$ts'];
$RH[$key][$i] = $data_arr[$i]['RH'];
$AT[$key][$i] = $data_arr[$i]['AT'];
$MINVi[$key][$i] = $data_arr[$i]['MINVi'];
$PTi[$key][$i] = $data_arr[$i]['PTi'];
$SDB[$key][$i] = $data_arr[$i]['SDB'];
$LWS[$key][$i] = $data_arr[$i]['LWS'];
$WSAV[$key][$i] = $data_arr[$i]['WSAV'];
$WSMX[$key][$i] = $data_arr[$i]['WSMX'];
$WSMN[$key][$i] = $data_arr[$i]['WSMN'];
$PR_TOT[$key][$i] = $data_arr[$i]['PR_TOT'];
$RAIN[$key][$i] = $data_arr[$i]['RAIN'];
$FDI[$key][$i] = $data_arr[$i]['FDI'];
$DT[$key][$i] = $data_arr[$i]['DT'];
$LAT[$key][$i] = $data_arr[$i]['LAT'];
$LON[$key][$i] = $data_arr[$i]['LON'];
$WD[$key][$i] = $data_arr[$i]['WD'];
$P1[$key][$i] = $data_arr[$i]['P1'];
$AVGCi[$key][$i] = $data_arr[$i]['AVGCi'];
$sql[$key][$i] = "INSERT INTO test(sn, date, RH, AT, MINVi, PTi, SDB, LWS, WSAV, WSMX, WSMN, PR_TOT, RAIN, FDI, DT, LAT, LON, WD, P1, AVGCi)
VALUES('{$id[$key][$i]}', '{$ts[$key][$i]}', '{$RH[$key][$i]}','{$AT[$key][$i]}', '{$MINVi[$key][$i]}', '{$PTi[$key][$i]}', '{$SDB[$key][$i]}', '{$LWS[$key][$i]}', '{$WSAV[$key][$i]}', '{$WSMX[$key][$i]}', '{$WSMN[$key][$i]}', '{$PR_TOT[$key][$i]}', '{$RAIN[$key][$i]}', '{$FDI[$key][$i]}', '{$DT[$key][$i]}', '{$LAT[$key][$i]}', '{$LON[$key][$i]}', '{$WD[$key][$i]}', '{$P1[$key][$i]}', '{$AVGCi[$key][$i]}')";
//insert into mysql table
$query[$key][$i] = mysqli_query($myConnection, $sql[$key][$i]) or die(mysqli_error($myConnection));
}
}
}
}
}
?>
I'm facing an issue regarding the json structure.
I have this:
function loadActiveTrackers($host_l, $username_l, $password_l, $dbName_l, $companyId_l){
$trackerId = 0;
$trackerName = "";
$trackerCreator = "";
$projectName = "";
$dataArray = [];
$trackerIdsArray = [];
$trackerNamesArray = [];
$trackerCreatorsArray = [];
$projectNamesArray = [];
$mysqli = new mysqli($host_l, $username_l, $password_l, $dbName_l);
$getActiveTrackersQuery = "SELECT tracker_id, tracker_name, tracker_creator, project_name FROM trackers WHERE "
. "company_id = ? AND is_active=1 ORDER BY tracker_creation_date";
if($stmt = $mysqli->prepare($getActiveTrackersQuery)){
$stmt->bind_param('s',$companyId_l);
$stmt->execute();
/* Store the result (to get properties) */
$stmt->store_result();
/* Bind the result to variables */
$stmt->bind_result($trackerId, $trackerName, $trackerCreator, $projectName);
while ($stmt->fetch()) {
$trackerIdsArray[] = $trackerId;
$trackerNamesArray[] = $trackerName;
$trackerCreatorsArray[] = $trackerCreator;
$projectNamesArray[] = $projectName;
}
$dataArray['ids'] = $trackerIdsArray;
$dataArray['names'] = $trackerNamesArray;
$dataArray['creators'] = $trackerCreatorsArray;
$dataArray['projectNames'] = $projectNamesArray;
// print_r($trackerIdsArray);
/* free results */
$stmt->free_result();
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
echo json_encode($dataArray);
}
The above code works ok, but the structure is not valid.
What I mean is that it returns:
{
"ids": [1,2,3,4],
"names": ["1","2","test tracker","test1"],
"creators": ["1","test","test","test"],
"projectNames": ["1","1","test project","test"]
}
But it is supposed to return:
[
{"id": 1, "name": "1", "creator": "1", "projectName": "1"},
{"id": 2, "name": "2", "creator": "test", "projectName": "1"},
{"id": 3, "name": "test tracker", "creator": "test", "projectName": "test project"},
{"id": 4, "name": "test1", "creator": "test", "projectName": "test"}
]
Can you guide me trough it? I know that it's something really small, but I'm not able to spot it as a php newbie. In java the json library is pretty strong and with a single push() it can be achieved, but here I really can't find the way.
The current code creates arrays of the ids, names, creators, and project names.
So, instead of this code:
while ($stmt->fetch()) {
$trackerIdsArray[] = $trackerId;
$trackerNamesArray[] = $trackerName;
$trackerCreatorsArray[] = $trackerCreator;
$projectNamesArray[] = $projectName;
}
$dataArray['ids'] = $trackerIdsArray;
$dataArray['names'] = $trackerNamesArray;
$dataArray['creators'] = $trackerCreatorsArray;
$dataArray['projectNames'] = $projectNamesArray;
Change your structure to be like so:
while ($stmt->fetch()) {
$dataArray[] = array( 'id' => $trackerId,
'name' => $trackerName,
'creator' => $trackerCreator,
'projectName' => $projectName
);
}
echo json_encode($dataArray);
This will return the structure you desire, which is arrays of the ids, names, creators, and project names.
I have 3 different tables in my database called consoleConsole, consoleModel, and consoleGame. Then what I want to do is that each console will have a loop inside for its models, and each models will have another loop inside for its games like this:
[
{
"Console":"PlayStation",
"Information":[
{
"Model":"PlayStation 3",
"Title":[
{
"Game":"007 Legends",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat: Assault Horizon",
"Publisher":"Namco"
}
]
},
{
"Model":"PlayStation 2",
"Title":[
{
"Game":"007: Agent of Fire",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat 4: Shattered Skies",
"Publisher":"Namco"
}
]
},
{
"Model":"PlayStation 1",
"Title":[
{
"Game":"007 Racing",
"Publisher":"Electronic Arts"
},
{
"Game":"Ace Combat",
"Publisher":"Namco"
}
]
}
]
},
{
"Console":"Wii",
"Information":[
{
"Model":"Wii",
"Title":[
{
"Game":"007: Quantum of Solace",
"Publisher":"Activision"
},
{
"Game":"AC/DC Live: Rock Band Track Rack",
"Publisher":"MTV Games"
}
]
}
]
},
{
"Console":"Xbox",
"Information":[
{
"Model":"Xbox",
"Title":[
{
"Game":"AFL",
"Publisher":"Acclaim"
},
{
"Game":"American Chopper",
"Publisher":"Activision"
}
]
},
{
"Model":"Xbox 360",
"Title":[
{
"Game":"AFL Live",
"Publisher":"Electronic Arts"
},
{
"Game":"Akai Katana Shin",
"Publisher":"Cave"
}
]
}
]
}
]
But sadly, I was not using my database with this one but instead I just wrote it straight in a php file.
EDIT
Anyways, moving on. I have modified my code and ended up like this.
<?PHP
$consoleQuery = "SELECT * ".
"FROM consoleConsole ".
"JOIN consoleModel ".
"ON consoleConsole.consoleId = consoleModel.consoleId ".
"JOIN consoleGame ".
"ON consoleModel.modelId = consoleGame.gameId";
$consoleResult = mysql_query($consoleQuery);
$consoleFields = array_fill_keys(array(
'consoleName',
), null);
$modelFields = array_fill_keys(array(
'modelName',
), null);
$console = array();
$rowConsole = array();
while ($rowConsole = mysql_fetch_assoc($consoleResult)) {
$consoleId = $rowConsole['consoleId'];
$modelId = $row['modelId'];
if (isset($console[$consoleId]['Information'])) {
$console[$consoleId]['Information'][] = array_intersect_key($rowConsole, $modelFields);
}
else {
$console[$consoleId] = array_intersect_key($rowConsole, $consoleFields);
$console[$consoleId]['Information'] = array(array_intersect_key($rowConsole, $modelFields));
}
}
$console = array_values($console);
echo json_encode($console);
?>
I was able to produce an output but it doesn't look like the output above.
[
{
"consoleName": "PlayStation",
"Information": [
{
"modelName": "PlayStation"
},
{
"modelName": "PlayStation 2"
},
{
"modelName": "PlayStation 3"
},
{
"modelName": "PlayStation 3"
}
]
},
{
"consoleName": "Wii",
"Information": [
{
"modelName": "Wii"
},
{
"modelName": "Wii"
}
]
},
{
"consoleName": "Xbox",
"Information": [
{
"modelName": "Xbox"
},
{
"modelName": "Xbox 360"
}
]
}
]
Their relations:
What my problem is right now, I can't add the Title of the each Game.
Ok so I have written up your solution. You have to be sure that the order by is included there because it assumes that you are ordering them with there items together. I also didnt know how your publisher was stored so I separated that out into a separate table (this will allow you to then get items by just there publisher as well), which is now 4 joins. Also on another note I have updated it to do inner joins as well. This way you will not get empty results for consoles that don't have any games assigned to them. If you want these you could simply change the joins so that it would give you those results as well. Let me know if this helps
//get all of the information
$query = '
SELECT c.consoleId,c.consoleName,m.modelId,m.modelName,g.gameId,g.gameName,p.publisherId,p.publisherName
FROM `consoleconsole` c
INNER JOIN `consolemodel` m ON c.consoleId=m.consoleId
INNER JOIN `consolegame` g ON m.modelId=g.modelId
INNER JOIN `consolepublisher` p ON g.publisherId = p.publisherId
ORDER BY c.consoleName, m.modelName, g.gameName
';
//get the results
$result = mysql_query($query);
//setup array to hold information
$consoles = array();
//setup holders for the different types so that we can filter out the data
$consoleId = 0;
$modelId = 0;
//setup to hold our current index
$consoleIndex = -1;
$modelIndex = -1;
//go through the rows
while($row = mysql_fetch_assoc($result)){
if($consoleId != $row['consoleId']){
$consoleIndex++;
$modelIndex = -1;
$consoleId = $row['consoleId'];
//add the console
$consoles[$consoleIndex]['console'] = $row['consoleName'];
//setup the information array
$consoles[$consoleIndex]['information'] = array();
}
if($modelId != $row['modelId']){
$modelIndex++;
$modelId = $row['modelId'];
//add the model to the console
$consoles[$consoleIndex]['information'][$modelIndex]['model'] = $row['modelName'];
//setup the title array
$consoles[$consoleIndex]['information'][$modelIndex]['title'] = array();
}
//add the game to the current console and model
$consoles[$consoleIndex]['information'][$modelIndex]['title'][] = array(
'game' => $row['gameName'],
'publisher' => $row['publisherName']
);
}
echo json_encode($consoles);
Since you are using php function to encode json , it will give you the json in its default format. what you have to do is create your own function using string manipulation to get desired result.