I have some JSON that looks like this:
{
"order_id":"59.1595",
"quantity":"1",
"orderline":"61b9f15a158ee",
"customer_id":"59",
"product_thumbnail":"https:\/\/website.nl\/cms\/images\/producten\/deelpaneel\/afbeeldingen\/_deelpaneel_foto_op_rvs.jpg",
"rulers":"cm",
"product_data":{
"id":"custom",
"dpi":"50",
"name":"Deelpaneel",
"size":"1000x550",
"bleed":"10",
"sides":{
"id":1,
"name":"Frontside",
"name_nl":"Voorkant",
"template_overlay":"https:\/\/website.nl\/cms\/images\/producten\/deelpaneel\/templates\/2_deelpaneel_100x55cm1cmafstandhouders.svg"
}
},
"safety":"",
"has_contour":"false",
"preview_link":"",
"redirect_link":"https:\/\/website.nl\/winkelwagen",
"procheck":"n"
}
I create it with PHP and use json_encode.
My question is how do I get brackets around the inside of sides?
Like in this example:
"sides": [
{
"id": 1,
"name": "Frontside",
"name_nl": "Voorkant",
"template_overlay": null
},
{
"id": 2,
"name": "2 side en",
"name_nl": "2 side nl",
"template_overlay": null
},
{
"id": 3,
"name": "3 side en",
"name_nl": "3 side nl",
"template_overlay": null
}
],
"safety": 10,
This is how I create that part with PHP:
<?PHP
if(!empty($uploadarray['product_data']['sides'])){
// Multiple sides
}else{
$uploadarray['product_data']['sides']['id'] = 1;
$uploadarray['product_data']['sides']['name'] = 'Frontside';
$uploadarray['product_data']['sides']['name_nl'] = 'Voorkant';
$uploadarray['product_data']['sides']['template_overlay'] = $templateoverlay;
}
?>
Then I create the entire JSON with: $json = json_encode($uploadarray);
I've read that you need to wrap it in another array but I can't get it to work.
For example:
array(array($uploadarray['product_data']['sides']['id'] = 1));
Or
array($uploadarray['product_data']['sides']['name'] = 'Frontside');
Just output the same json result.
First create your array
$side = [
'id' => 1,
'name' => 'Frontside',
'name_nl' => 'Voorkant',
'template_overlay' => $templateoverlay
];
Then, add it :
// Check this -----------------------vv
$uploadarray['product_data']['sides'][] = $side;
Your $sides variable does not contain an array with multiple entities but just one "dictionary" (one JSON object). If you e.g. add a loop around, it should work:
<?php
// loop over whatever generates the sides
$sides_array = [];
$sides_array['id'] = 1;
$sides_array['name'] = 'Frontside';
$sides_array['name_nl'] = 'Voorkant';
$sides_array['template_overlay'] = $templateoverlay;
if(empty($uploadarray['product_data']['sides'])){
// initialize "sides"
$uploadarray['product_data']['sides'] = [];
}
$uploadarray['product_data']['sides'][] = $sides_array;
?>
I have a JSON source and I am trying to loop trough it and show some results (up to 9 results) which is not a problem
The problem is that I want to show only the results that are matching a certain date, where the date might be exact or between 2 dates.
For example I want to show only the events where let say the date 2019-11-17 is within timeFrom timeTo of the event or timeFrom or timeTo is equal to it. In that example it will be event 1 and 3
This is the source sample
{
"title":"event 1",
"timeFrom":"2019-11-16 19:00:00",
"timeTo":"2019-11-18 22:00:00",
"listText":"text of the event",
"url":"https://url",
"imageUrl":"https://image.jpg",
"locations":{
"title":"Location name",
"url":"https://location"
}
},
{
"title":"event 2",
"timeFrom":"2019-11-20 19:00:00",
"timeTo":"2019-11-20 22:00:00",
"listText":"text of the event",
"url":"https://url",
"imageUrl":"https://image.jpg",
"locations":{
"title":"Location name",
"url":"https://location"
}
},
{
"title":"event 3",
"timeFrom":"2019-11-17 19:00:00",
"timeTo":"2019-11-17 22:00:00",
"listText":"text of the event",
"url":"https://url",
"imageUrl":"https://image.jpg",
"locations":{
"title":"Location name",
"url":"https://location"
}
And this is the foreach I have at the moment
foreach(array_slice($arr, 0, 9) as $data) {
//then I will show the result
}
So, I can't figure out how to make that condition within the foreach.
This function iterates through the events data, looking for events whose from and to dates surround the given date:
function find_events($events, $date) {
$date = new DateTime($date);
foreach ($events as $event) {
$from = (new DateTime($event['timeFrom']))->setTime(0,0,0);
$to = (new DateTime($event['timeTo']))->setTime(0,0,0);
if ($date >= $from && $date <= $to) {
echo "{$event['title']} ({$event['listText']}) from {$event['timeFrom']} to {$event['timeTo']}\n";
}
}
}
$events = json_decode($json, true);
find_events($events, '2019-11-17');
Output:
event 1 (text of the event) from 2019-11-16 19:00:00 to 2019-11-18 22:00:00
event 3 (text of the event) from 2019-11-17 19:00:00 to 2019-11-17 22:00:00
Demo on 3v4l.org
Try this code:
$date = "2019-11-17";
$events = json_decode($json_output, true);
foreach ($events as $event)
{
if (($date > $event['timeFrom'] && $date < $event['timeTo']) || in_array($date, array($event['timeFrom'], $event['timeTo'])))
{
$filtered_events[] = $event;
}
}
$sliced_events = array_slice($filtered_events, 0, 9);
print_r($sliced_events);
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));
}
}
}
}
}
?>
(First a bit/lot of context at the bottom is the question)
I am writing an API that returns a planning amongst other things. The response is in JSON and should be as followed:
"Planning":
[
{
"Name": "Overview",
"Dates":
[
{
"Date": "yyyy-mm-dd",
"Division1": "type",
"Division2": "type"
},
{
"Date": "yyyy-mm-dd",
"Division1": "type",
"Division2": "type"
},
...
]
},
{
"Name": "Division1",
"Dates":
[
{
"Date": "yyyy-mm-dd",
"Type": "type",
"Description": "type"
},
...
]
},
...
There is the standard blok "Name": "Overview" this is always returned, and for each division the requester is a part of, a block with "Name":"Divisionname" is added to the response.
The issue I have is that the amount or names of the divisions aren't set in stone. There can be more or less depending on the deployment.
To cover for this I wrote the following code:
<?php
...
$stmt = $conn->prepare("SELECT `idDivision` FROM Division;");
$stmt->execute();
$stmt->bind_result($idDivision);
while($stmt->fetch()){
$Divisions[] = $idDivision;
$$idDivision = array();
}
...
?>
This should create an array for each division with the array name being the id of that division (correct?).
Then I get the planning data from the DB which i store in the multiple arrays that I will later use for the response building:
<?php
$stmt->bind_result($type, $date, $idDivision, $day, $description, $note);
while($stmt->fetch()){
if(checkarray($date, $arr_date) != true){
array_push($arr_date, $date);
array_push($arr_day, $day);
}
array_push($$idDivision, $type); //This should push it into the correct array.
}
?>
At the end I want to combine all this into the respons ofcourse (This is where I am lost):
<?php
for($i = 0; $i <= count($arr_date); $i++){
$planning[0]['Dates'][] = array(
"Date" => $arr_date[$i],
// How to add every division with "arrayname" => "$type" here?
);
}
?>
As in the comment above, i don't know how to add a key:value for each division that i found dynamically so that it becomes:
<?php
for($i = 0; $i <= count($arr_date); $i++){
$planning[0]['Dates'][] = array(
"Date" => $arr_date[$i],
"Division1" => $value,
"Division2" => $value,
"Division3" => $value,
// and so on for every division
);
}
?>
Is there a way to do this or should I even go about doing this a different way? I feel like I should/could use the $Divisions array.
Try out this.
for($i = 0; $i <= count($arr_date); $i++){
$planning[0]['Dates'][$i]["Date"] = $arr_date[$i];
for($j=0;$j<count($division);$j++){
$planning[0]['Dates'][$i]["division$j"] = $division[$j];
}
}
?>