Need to create Json object in php - php

I want to create a json object using php like below as I need to create a stacked bar chart using d3.js, hence I am using data from oracle table and need the json data as above image.
My table has these 3 columns. (ID, NAME, Layers) like:-
ID, NAME, Layers
1 ABC a:8,b:10
2 WWW c:8,d:7
When I am fetching data from oracle, my php code is:-
while (($row = oci_fetch_array($stid, OCI_ASSOC))) {
$streamArr[] = $row;
}
header("Access-Control-Allow-Origin: *");
echo json_encode($streamArr);
I am getting this error:-
Warning: [json] (php_json_encode) type is unsupported, encoded as null in line 48
json output as:-
[["1","ABC",{"descriptor":null}],["2","WWW",{"descriptor":null}]]
can you please help me in rectifying with this issue?

The error message refers to a field you didn't mention in the example. Maybe just don't select unneeded fields?
If you fix that, you still won't get the desired JSON structure. To get layers as an object in every element of data in the resulting JSON, you need to convert the string values stored in the database to PHP arrays before encoding.
You could do that with similar code:
while (($row = oci_fetch_array($stid, OCI_ASSOC)))
{
$row['layers'] = array_map(function($el) {
return explode(':', $el);
}, explode(',', $row['layers']));
$streamArr[] = $row;
}

#marekful answer is really nice, not easiest to understand but efficient and short!
Here you have a longer and not so efficient, but maybe easier to get.
$streamArr = array();
while (($row = oci_fetch_array($stid, OCI_ASSOC)))
{
// Get ID and NAME
$data = array(
'id' => $row['ID'],
'name' => $row['NAME'],
'layers' => array()
);
// Get Layers by split by comma
$layers = explode(',', $row['layers']);
foreach ($layers as $layer) {
// Get layer parts by slit with double-point
$layersPart = explode(':', $layer);
foreach ($layersPart as $key => $value) {
$data['layers'][$key] = $value;
}
}
// Add to global array
$streamArr[] = $data;
}
echo json_encode($streamArr);

Related

How to make key value by explode and arrange matching key values into one key?

I am recently facing a practical problem.I am working with ajax form submission and there has been some checkboxes.I need all checkboxes with same name as key value pair.Suppose there is 4 checkboxes having name attribute =checks so i want something like $arr['checks'] = array(value1, value2, ...)
So i am getting my ajax $_POST code as suppose like: name=alex&checks=code1&checks=code2&checks=code3
I am using below code to make into an array
public function smdv_process_option_data(){
$dataarray = array();
$newdataarray = array();
$new = array();
$notices = array();
$data = $_POST['options']; // data received by ajax
$dataarray = explode('&', $data);
foreach ($dataarray as $key => $value) {
$i = explode('=', $value);
$j = 1;
if(array_key_exists($i[0], $newdataarray)){
if( !is_array($newdataarray[$i[0]]) ){
array_push($new, $newdataarray[$i[0]]);
}else{
array_push($new, $i[1]);
}
$newdataarray[$i[0]] = $new;
}else{
$newdataarray[$i[0]] = $i[1];
}
}
die($newdataarray);
}
Here i want $newdataarray as like below
array(
'name' => 'alex',
'checks => array(code1, code2, code3),
)
But any how I am missing 2nd value from checks key array.
As I see it you only need to do two explode syntaxes.
The first on is to get the name and here I explode on & and then on name= in order to isolate the name in the string.
The checks is an explode of &checks= if you omit the first item with array_slice.
$str = 'name=alex&checks=code1&checks=code2&checks=code3';
$name = explode("name=", explode("&", $str)[0])[1];
// alex
$checks = array_slice(explode("&checks=", $str), 1);
// ["code1","code2","code3"]
https://3v4l.org/TefuG
So i am getting my ajax $_POST code as suppose like: name=alex&checks=code1&checks=code2&checks=code3
Use parse_str instead.
https://php.net/manual/en/function.parse-str.php
parse_str ( string $encoded_string [, array &$result ] ) : void
Parses encoded_string as if it were the query string passed via a URL and sets variables in the current scope (or in the array if result is provided).
$s = 'name=alex&checks=code1&checks=code2&checks=code3';
parse_str($s, $r);
print_r($r);
Output
Array
(
[name] => alex
[checks] => code3
)
You may think this is wrong because there is only one checks but technically the string is incorrect.
Sandbox
You shouldn't have to post process this data if it's sent correctly, as that is not included in the question, I can only make assumptions about it's origin.
If your manually creating it, I would suggest using serialize() on the form element for the data for AJAX. Post processing this is just a band-aid and adds unnecessary complexity.
If it's from a source outside your control, you'll have to parse it manually (as you attempted).
For example the correct way that string is encoded is this:
name=alex&checks[]=code1&checks[]=code2&checks[]=code3
Which when used with the above code produces the desired output.
Array
(
[name] => alex
[checks] => Array
(
[0] => code1
[1] => code2
[2] => code3
)
)
So is the problem here, or in the way it's constructed...
UPDATE
I felt obligated to give you the manual parsing option:
$str = 'name=alex&checks=code1&checks=code2&checks=code3';
$res = [];
foreach(explode('&',$str) as $value){
//PHP 7 array destructuring
[$key,$value] = explode('=', $value);
//PHP 5.x list()
//list($key,$value) = explode('=', $value);
if(isset($res[$key])){
if(!is_array($res[$key])){
//convert single values to array
$res[$key] = [$res[$key]];
}
$res[$key][] = $value;
}else{
$res[$key] = $value;
}
}
print_r($res);
Sandbox
The above code is not specific to your keys, which is a good thing. And should handle any string formatted this way. If you do have the proper array format mixed in with this format you can add a bit of additional code to handle that, but it can become quite a challenge to handle all the use cases of key[] For example these are all valid:
key[]=value&key[]=value //[key => [value,value]]
key[foo]=value&key[bar]=value //[key => [foo=>value,bar=>value]]
key[foo][]=value&key[bar][]=value&key[bar][]=value //[key => [foo=>[value]], [bar=>[value,value]]]
As you can see that can get out of hand real quick, so I hesitate to try to accommodate that if you don't need it.
Cheers!

PHP extract key-value in array json and restructure

Any idea on how to restructure the json below:
$jsonArray = [{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]
Expected outcome:
$expected = {"Milk":{"Level":"77.2023%","Temperature":"4"},
"Coffee":{"Level":"399.2023%","Temperature":"34"},
"Chocolate":{"Level":"109.2023%","Temperature":"14"}
}
I'm new and my thinking is get the product value in array and again use foreach loop to find the others value? .
Here's one possibility:
$jsonArray = '[{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]';
$output = array();
foreach (json_decode($jsonArray, true) as $row) {
$product = $row['Product'];
$output[$product] = $row;
unset($output[$product]['Product']);
}
echo json_encode($output);
Output:
{"Milk":{"Level":"77.2023%","Temperature":"4"},
"Coffee":{"Level":"399.2023%","Temperature":"34"},
"Chocolate":{"Level":"109.2023%","Temperature":"14"}
}
Demo on 3v4l.org
This made some trick
$a = '[{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]';
$newAr = array();
foreach(json_decode($a,true) as $key=>$value)
{
$newAr[$value['Product']] = array(
'Level' => $value['Level'],
'Temperature' => $value['Temperature'],
);
}
There are many ways to perform this with Loops in PHP. Other answers demonstrate it accurately. I would also suggest to integrate some form of Error handling, data validation/filtering/restriction in your code to avoid unexpected results down the road.
For instance, json_decode(), either assigned to a variable pre-foreach or straight in the foreach() 1st argument will just raise a warning if the original json is not valid-json, and just skip over the foreach used to construct your final goal. Then if you pass the result (that may have failed) directly to your next logic construct, it could create some iffy-behavior.
Also, on the concept of data-validation & filtering, you could restrict the foreach(), or any other looping mechanism, to check against a Product_List_Array[Milk,Coffee,Chocolate], using if(in_array() ...) so the final/goal object only contains the expected Products, this, in the case the original json has other artifacts. Filtering the values can also increase stability in restricting, for example, Temperature to Float.

Trying to get correct/exact string from json

I am trying to get string from JSON, that i should use later. The problem is that my code (depending which file i use) doesn't give me my string with special characters. Strange thing is that one file does everything right, while other is not, even through they contain exactly the same PHP code.
This is that i get from the first one:
[title] => 1611 Plikiškiai–Kriukai (Incorrect)
And from another:
[title] => 1611 Plikiškiai–Kriukai (Correct one)
Here is some code:
function get_info($id) {
$json = file_get_contents('http://restrictions.eismoinfo.lt/');
$array = json_decode($json, true);
//get object/element with such id, so then it would be possible take needed parts/values
$result_array = array();
foreach ($array as $key => $value) {
if ($id == $value['_id']){
$result_array = $value;
}
}
//Street name
$title = $result_array['location']['street'];
echo $title;
}
get_info($id); //$id is some string like 143crt9tDgh5
1st file is located in folder "test", while 2nd in "project".
Any ideas why is that happening?

How to get access to class field which is variable

Firstly, look my example json output.
I have next question. I have some fields in json code like 'counter_87' or 'coutner_88' in countersData part. It is a variable. I need to get access to this variable class field.
Ofc, I can write:
foreach($objCounter->countersData as $data)
{
print $data->counter_87;
}
It is working fine. But...
I have counters ID and I need to get access to fields which are named depending on this ID's.
Full code, which will show what I want:
foreach($objCounter->countersData as $data)
{
$row = "<td width=100px>$data->month $data->year</td>";
foreach($objCounter->counters as $counter)
{
$counterId = $counter->id;
$counterValue = "$data->counter_$counterId";
$row .= "<td>$counterValue</td>";
}
$table .= "<tr>$row</tr>";
}
I need same:
$foo = 'bar';
$bar = 'foobar';
echo $$foo; // foobar will be printed
But with classes.
Thank you.
You could also do the following if you don't want to or can't change change your JSON structure as already mentioned in the comments.
$field_name = 'counter_'.$id;
$field_value = $data->$field_name;
$row .= "<td>$field_value</td>";
// or $row .= '<td>'.$data->$field_name.'</td>';
About rewriting the JSON. Here's code that would convert your JSON to the slightly better structure.
$data = json_decode($data_json);
foreach($data->countersData as $counter_data) {
$counters = array();
foreach($counter_data as $key => $val) {
if(substr($key, 0, 8) == 'counter_') {
$counters[substr($key, 8)] = $val;
unset($counter_data->$key);
}
}
$counter_data->counters = $counters;
}
$data_json_new = json_encode($data);
Using an array instead of fields like 'counter_1', 'counter_2' means having structure like this this:
$countersData[0]->counters[90] = 1;
$countersData[0]->counters[89] = 1;
$countersData[0]->counters[88] = 1;
Instead of
$countersData[0]->counters_90 = 1;
$countersData[0]->counters_89 = 1;
$countersData[0]->counters_88 = 1;
This means having an associative array called counters instead of separate fields like 'counter_90' or something. It makes accessing the data programmatically alot easier.
Note that associative array is very similar to the stdClass. Basically a different datatype serving the same purpose. Using an array to represent your data just makes it easier to deal with integer keys. You can use json_decode($data_json, true) to get the data returned as an associative array.

Complex JSON array to MySQL via PHP

I'm aiming to put a selection of info from a JSON result into MySQL via PHP. The specific issue I'm having is with accessing specific info from the JSON result, as it isn't a simple list format. Here is a screenshot of the kind of structure I'm talking about with the information I'm interested in highlighted.:
I sadly don't have enough reputation to post an image so here it is rehosted on imgur:
Under ['streams'] will be a list of 100 streams. From each of those results I want to take the highlighted information and place it into a MySQL table.
I'm fairly comfortable with simpler JSON files and easier applications of json_decode
$result = json_decode($json);
foreach ($result as $key => $value)
I'm thinking perhaps I need to use the depth variable? But finding it difficult to find much information on it.
If anyone can give me any help or point me towards a good source of info (As I have struggled to find anything) then it would be much appreciated.
If anymore information would be useful let me know and I will add it.
edit: link to json request: https://api.twitch.tv/kraken/streams?limit=2/
<?php
//import data from twitch
$json = json_decode(file_get_contents("https://api.twitch.tv/kraken/streams?limit=100/"), true);
//create a DB connection
$con = mysql_connect("CONNECTION INFO :D");
mysql_connect_db('NOPE', $con);
$result = json_decode($json);
foreach ($result as $key => $value) {
if ($value) {
mmysql_query("INSERT INTO twitchinfo (viewers, status, display_name, game, delay, name) VALUES ($value->viewers, $value->status,$value->display_name,$value->game,$value->delay,$value->name)")or die(mysql_error());
}
// end connection
mysql_close($con);
}
?>
Your JSON object is basically something like...
[
links: {
self: http://example.com,
next: http://example.com/foo,
},
streams: [
{
channel: {
foo: 'bar'
},
one: 'one',
somethingElse: 'Something else',
moreStuff: 'more stuff',
}
]
]
When you decode a JSON object you are left with a PHP Object/Array that represents the object.
$x = json_decode('[1,2,3]')
is going to give you the same array as...
$x= array(1,2,3)
If you load up the JSON you've shown and run this:
foreach ($result as $key => $value)
This is the same as accessing $result->links and $result->streams. Each contains more data.
If I wanted to grab the 'foo' element from the channel in my example I would do:
$streams = $result->streams //Get the streams array
$stream = $streams[0] //Get the first stream object
$channel = $stream->channel //Get the channel object
$foo = $channel->foo //Get the value 'bar' out of the foo property.
As long as the structure is predictable (and it is), I can iterate over the streams since it's just an array.
$streams = $result->streams //Get the streams array
foreach ($streams as $stream) {
$channel = $stream->channel //Get the channel object
$foo = $channel->foo //Get the value 'bar' out of the foo property of every stream.
}
Opening this url in browser -
https://api.twitch.tv/kraken/streams?limit=100/
Gives me a JSON. I copied it in -
http://www.jsoneditoronline.org/
and saw that it has streams and _links keys.
As per your issue is concerned, try this -
$result = json_decode($json);
if( isset( $result['streams'] )){
$streams = $result['streams'];
foreach($streams as $stream) {
$viewers = $stream->viewers;
$status = $stream->channel->status;
$display_name = $stream->channel->display_name;
$game = $stream->channel->game;
$delay = $stream->channel->delay;
$name = $stream->channel->name;
$sql = "INSERT INTO twitchinfo (viewers, status, display_name, game, delay, name) VALUES ($viewers, \"$status\", \"$display_name\", \"$game\", $delay, \"$name\")";
mysql_query($sql)or die(mysql_error());
}
}
May be you can do this:
$values = array();
$result = json_decode($json);
foreach($result['streams'] as $stream) {
array_push(
$values,
array(
'viewers' => $stream['viewers'],
'status' => $stream['channel']['status'],
'display_name' => $stream['channel']['display_name'],
'game' => $stream['channel']['game'],
'delay' => $stream['channel']['delay'],
'name' => $stream['channel']['name'],
)
);
}
Or:
foreach($result['streams'] as $stream) {
$sqlQuery= "INSERT INTO TABLE(viewers, status, display_name, game, delay, name) VALUES ($stream['viewers'], $stream['channel']['status'], $stream['channel']['display_name'], $stream['channel']['game'], $stream['channel']['delay'], $stream['channel']['name']);"
//dbHandler->executeQuery($sqlQuery);
}

Categories