Decode a JSON file with PHP - json

I have a classic JSON problem, and i know that many post are asking about that...
But i doubt that the JSON i try to grab has a correct structure.
The files Begin like that :
[{
"time":"0-12h",
"articles":[
{
"id":1,
"domain_id":22,
"title":"Hi Guys"
}
{
"id":2,
"domain_id":17,
"title":"Hi everyone"
}
]
}]
I have try a lot of combinaison to echo the title :
$data = json_decode($json, true);
echo $data->articles;
Or
echo $data->articles->title;
Or
echo $data->articles[0]->title;
Nothing works... :(
Can you help me ?
Thanks !

The second argument true to json_decode() means it should create associative arrays rather than objects for {} in the JSON. So in addition to dealing with the indexed arrays as Explosion Pills points out, you also need to use array syntax to access the keyed elements:
$data[0]['articles'][0]['title']
If you want to be able to use -> syntax, leave out the second argument or set it to false.
I'm hoping the missing comma in the JSON is an error when transcribing to the question. If not, you also need to fix the code that creates the JSON in the first place.

$data itself is an array. Try
$data[0]->articles[0]->title;
Also the JSON is not valid (missing a comma before the second articles array element).

there is a comma , missing
}
,
{
json_decode with the second parameter true returns an array
print_r($data['articles']);
echo $data['articles'] would output Array

Related

Redshift JSON Parsing

I have some JSON data in Redshift table of type character varying. An example entry is:
[{"value":["*"], "key":"testData"}, {"value":"["GGG"], key: "differentData"}]
I want to return vales based on keys, how can i do this? I'm attempting to do something like
json_extract_path_text(column, 'value') but unfortunately it errors out. Any ideas?
So the first issue is that your string isn't valid JSON. There are mismatched and missing quotes. I think you mean:
[{"value":["*"], "key":"testData"}, {"value":["GGG"], "key": "differentData"}]
I don't know if this is a data issue or a transcription error but these functions won't work unless the json text is valid.
The next thing to consider is that at the top level this json is an array so you will need to use json_extract_array_element_text() function to pick up an element of the array. For example:
json_extract_array_element_text('json string', 0)
So putting this together we can extract the first "value" with (untested):
json_extract_path_text(
json_extract_array_element_text(
'[{"value":["*"], "key":"testData"}, {"value":["GGG"], "key": "differentData"}]', 0
), 'value'
)
Should return the string ["*"].

file_put_contents('items.json',json_encode($item));

How to create a json file in laravel to store data in json format so that I can use it in ajax coz I'm having problem in autocomplete search. I have done this but it worked in Category not in item.
$catagories=Catagory::where('status',1)->get(['name'])->toArray();
$items=Item::where('status',1)->get()->toArray();
$cats=array();
$item=array();
foreach($catagories as $cat){
array_push($cats,$cat['name'])
}
file_put_contents('category.json',json_encode($cats));
file_put_contents('items.json',json_encode($item));
Your variable $item is never used, so it won't print anything on the file. You need to use the $items variable
Try
file_put_contents('items.json',json_encode($items));
I think that it is because your item array is empty
$catagories=Catagory::where('status',1)->get(['name'])->toArray();
$items=Item::where('status',1)->get()->toArray();
$cats=array();
$item=array();
foreach($catagories as $cat){
array_push($cats,$cat['name'])
}
file_put_contents('category.json',json_encode($cats));
file_put_contents('items.json',json_encode($item));
You are using $item array on last line which is empty, coz you didn't fill it from $items array

Decoding and using JSON data in Perl

I am confused about accessing the contents of some JSON data that I have decoded. Here is an example
I don't understand why this solution works and my own does not. My questions are rephrased below
my $json_raw = getJSON();
my $content = decode_json($json_raw);
print Data::Dumper($content);
At this point my JSON data has been transformed into this
$VAR1 = { 'items' => [ 1, 2, 3, 4 ] };
My guess tells me that, once decoded, the object will be a hash with one element that has the key items and an array reference as the value.
$content{'items'}[0]
where $content{'items'} would obtain the array reference, and the outer $...[0] would access the first element in the array and interpret it as a scalar. However this does not work. I get an error message use of uninitialized value [...]
However, the following does work:
$content->{items}[0]
where $content->{items} yields the array reference and [0] accesses the first element of that array.
Questions
Why does $content{'items'} not return an array reference? I even tried #{content{'items'}}, thinking that, once I got the value from content{'items'}, it would need to be interpreted as an array. But still, I receive the uninitialized array reference.
How can I access the array reference without using the arrow operator?
Beginner's answer to beginner :) Sure not as profesional as should be, but maybe helps you.
use strict; #use this all times
use warnings; #this too - helps a lot!
use JSON;
my $json_str = ' { "items" : [ 1, 2, 3, 4 ] } ';
my $content = decode_json($json_str);
You wrote:
My guess tells me that, once decoded, the object will be a hash with
one element that has the key items and an array reference as the value.
Yes, it is a hash, but the the decode_json returns a reference, in this case, the reference to hash. (from the docs)
expects an UTF-8 (binary) string and tries to parse that
as an UTF-8 encoded JSON text,
returning the resulting reference.
In the line
my $content = decode_json($json_str);
you assigning to an SCALAR variable (not to hash).
Because you know: it is a reference, you can do the next:
printf "reftype:%s\n", ref($content);
#print: reftype:HASH ^
#therefore the +------- is a SCALAR value containing a reference to hash
It is a hashref - you can dump all keys
print "key: $_\n" for keys %{$content}; #or in short %$content
#prints: key: items
also you can assing the value of the "items" (arrayref) to an scalar variable
my $aref = $content->{items}; #$hashref->{key}
#or
#my $aref = ${$content}{items}; #$hash{key}
but NOT
#my $aref = $content{items}; #throws error if "use strict;"
#Global symbol "%content" requires explicit package name at script.pl line 20.
The $content{item} is requesting a value from the hash %content and you never defined/assigned such variable. the $content is an scalar variable not hash variable %content.
{
#in perl 5.20 you can also
use 5.020;
use experimental 'postderef';
print "key-postderef: $_\n" for keys $content->%*;
}
Now step deeper - to the arrayref - again you can print out the reference type
printf "reftype:%s\n", ref($aref);
#reftype:ARRAY
print all elements of array
print "arr-item: $_\n" for #{$aref};
but again NOT
#print "$_\n" for #aref;
#dies: Global symbol "#aref" requires explicit package name at script.pl line 37.
{
#in perl 5.20 you can also
use 5.020;
use experimental 'postderef';
print "aref-postderef: $_\n" for $aref->#*;
}
Here is an simple rule:
my #arr; #array variable
my $arr_ref = \#arr; #scalar - containing a reference to #arr
#{$arr_ref} is the same as #arr
^^^^^^^^^^ - array reference in curly brackets
If you have an $arrayref - use the #{$array_ref} everywhere you want use the array.
my %hash; #hash variable
my $hash_ref = \%hash; #scalar - containing a reference to %hash
%{$hash_ref} is the same as %hash
^^^^^^^^^^^ - hash reference in curly brackets
If you have an $hash_ref - use the %{$hash_ref} everywhere you want use the hash.
For the whole structure, the following
say $content->{items}->[0];
say $content->{items}[0];
say ${$content}{items}->[0];
say ${$content}{items}[0];
say ${$content->{items}}[0];
say ${${$content}{items}}[0];
prints the same value 1.
$content is a hash reference, so you always need to use an arrow to access its contents. $content{items} would refer to a %content hash, which you don't have. That's where you're getting that "use of uninitialized value" error from.
I actually asked a similar question here
The answer:
In Perl, a function can only really return a scalar or a list.
Since hashes can be initialized or assigned from lists (e.g. %foo = (a => 1, b => 2)), I guess you're asking why json_decode returns something like { a => 1, b => 2 } (a reference to an anonymous hash) rather than (a => 1, b => 2) (a list that can be copied into a hash).
I can think of a few good reasons for this:
in Perl, an array or hash always contains scalars. So in something like { "a": { "b": 3 } }, the { "b": 3 } part has to be a scalar; and for consistency, it makes sense for the whole thing to be a scalar in the same way.
if the hash is quite large (many keys at top-level), it's pointless and expensive to iterate over all the elements to convert it into a list, and then build a new hash from that list.
in JSON, the top-level element can be either an object (= Perl hash) or an array (= Perl array). If json_decode returned a list in the former case, it's not clear what it would return in the latter case. After decoding the JSON string, how could you examine the result to know what to do with it? (And it wouldn't be safe to write %foo = json_decode(...) unless you already knew that you had a hash.) So json_decode's behavior works better for any general-purpose library code that has to use it without already knowing very much about the data it's working with.
I have to wonder exactly what you passed as an array to json_decode, because my results differ from yours.
#!/usr/bin/perl
use JSON qw (decode_json);
use Data::Dumper;
my $json = '["1", "2", "3", "4"]';
my $fromJSON = decode_json($json);
print Dumper($fromJSON);
The result is $VAR1 = [ '1', '2', '3', '4' ];
Which is an array ref, where your result is a hash ref
So did you pass in a hash with element items which was a reference to an array?
In my example you would get the array by doing
my #array = #{ $fromJSON };
In yours
my #array = #{ $content->{'items'} }
I don't understand why you dislike the arrow operator so much!
The decode_json function from the JSON module will always return a data reference.
Suppose you have a Perl program like this
use strict;
use warnings;
use JSON;
my $json_data = '{ "items": [ 1, 2, 3, 4 ] }';
my $content = decode_json($json_data);
use Data::Dump;
dd $content;
which outputs this text
{ items => [1 .. 4] }
showing that $content is a hash reference. Then you can access the array reference, as you found, with
dd $content->{items};
which shows
[1 .. 4]
and you can print the first element of the array by writing
print $content->{items}[0], "\n";
which, again as you have found, shows just
1
which is the first element of the array.
As #cjm mentions in a comment, it is imperative that you use strict and use warnings at the start of every Perl program. If you had those in place in the program where you tried to access $content{items}, your program would have failed to compile, and you would have seen the message
Global symbol "%content" requires explicit package name
which is a (poorly-phrased) way of telling you that there is no %content so there can be no items element.
The scalar variable $content is completely independent from the hash variable %content, which you are trying to access when you write $content{items}. %content has never been mentioned before and it is empty, so there is no items element. If you had tried #{$content->{items}} then it would have worked, as would #{${$content}{items}}
If you really have a problem with the arrow operator, then you could write
print ${$content}{items}[0], "\n";
which produces the same output; but I don't understand what is wrong with the original version.

Perl to JSON, with key/value pairs

I am trying to output some data from Perl to JSON. I can do a simple output, but would like to structure it better.
I have an array with an id, a start time and an end time. This is the code I am using to output:
print header('application/json');
my $json->{$entry} = \#array;
my $json_text = to_json($json);
print $json_text;
Which returns:
{"Season":[["1","1330065300","1344038401"],["7","1298505601","1312416001"]]}
But I would like to output something more like:
{"Season":0[{"id":1,"DateStart":1330065300,"DateEnd":1344038401},{"id":7,"DateStart":1298505601,"DateEnd":1312416001}]}
Can anyone help on how to better structure my output?
---UPDATE------
Thanks Michael. I have tried to implement your example.
This is the code at the moment:
foreach my $key (keys %$seasons)
{
$seasons->{$key} =
[
map
{
{ id=>$_[0], DateStart=>$_[1], DateEnd=>$_[2] }
} #{$seasons->{$key}}
];
}
But it returns the error (referring to the foreach line):
Not a HASH reference at line 148
$seasons is an arrayref return from a SQL fetchall_arrayref
Any clues?
You basically want to convert an array of arrays to an array of hashes, and you can do this using map. Assuming $data is your structure, this should do it:
for my $key (keys %$data) {
$data->{$key} = [
map {
{ id => $_->[0], DateStart => $_->[1], DateEnd => $_->[2] }
} #{$data->{$key}}
];
}
If you want to output an array of objects with key/value pairs instead of an array of arrays, then put appropriate data into to_json in the first place.
i.e. an array of hashrefs and not an array of arrayrefs.
You can use map to transform the data.
Whenever you're trying something like this, always check CPAN to see if someone has done it before and not try to reinvent the wheel. I found a module called JSON that seems to do exactly what you want.
There's an example on that page that does exactly what you want. Here's a quick paraphrase:
use JSON; # imports encode_json, decode_json, to_json and from_json.
# simple and fast interfaces (expect/generate UTF-8)
my $utf8_encoded_json_text = encode_json \#array;
Can't get easier than that. The best part is that this will work no matter how complex your array structure gets.

Data column(s) for axis #0 cannot be of type string error in google chart

I tried to populate google chart datatable in server side using PHP.I got JSON file properply, but the Chart not display in client Application. I got error-Data column(s) for axis #0 cannot be of type string . My coding is below here.
After fetching data from database,
$colarray=array(array("id"=>"","label"=>"userid","pattern"=>"","type"=>"number"),array("id"=>"","label"=>"name","pattern"=>"","type"=>"string"));
$final=array();
for($i=0;$i<$rows;$i++)
{
$id[$i]=pg_fetch_result($res1,$i,'id');
$name[$i]=pg_fetch_result($res1,$i,'name');
$prefinal[$i]=array("c"=>array(array("v"=>$name[$i]),array("v"=>$name[$i])));
array_push($final,$prefinal[$i]);
}
$table['cols']=$colarray;
$table['rows']=$final;
echo json_encode($table);
My Output Json:
{
"cols":[
{"id":"","label":"userid","pattern":"","type":"number"},
{"id":"","label":"name","pattern":"","type":"string"}
],
"rows":[
{"c":[{"v":"101"},{"v":"Aircel"}]},
{"c":[{"v":"102"},{"v":"Srini"}]},
{"c":[{"v":"103"},{"v":"Tamil"}]},
{"c":[{"v":"104"},{"v":"Thiyagu"}]},
{"c":[{"v":"105"},{"v":"Vasan"}]},
{"c":[{"v":"107"},{"v":"Senthil"}]},
{"c":[{"v":"108"},{"v":"Sri"}]},
{"c":[{"v":"109"},{"v":"Docomo"}]},
{"c":[{"v":"106"},{"v":"Innodea"}]}
]
}
How to solve this issue?
To extend on #sajal's accurate answer: Change the last line of your code from:
echo json_encode($table);
to:
echo json_encode($table, JSON_NUMERIC_CHECK);
This will tell json_encode to recognize numbers and abstain from wrapping them in quotes (Available since PHP 5.3.3.).
http://php.net/manual/en/json.constants.php#constant.json-numeric-check
You specify type of userid as number... but pass string.. thats causing the problem.
I just wasted 30 mins with the opposite problem ...
Your output json should look like :-
{
"cols":[
{"id":"","label":"userid","pattern":"","type":"number"},
{"id":"","label":"name","pattern":"","type":"string"}
],
"rows":[
{"c":[{"v":101},{"v":"Aircel"}]},
{"c":[{"v":102},{"v":"Srini"}]},
{"c":[{"v":103},{"v":"Tamil"}]},
{"c":[{"v":104},{"v":"Thiyagu"}]},
{"c":[{"v":105},{"v":"Vasan"}]},
{"c":[{"v":107},{"v":"Senthil"}]},
{"c":[{"v":108},{"v":"Sri"}]},
{"c":[{"v":109},{"v":"Docomo"}]},
{"c":[{"v":106},{"v":"Innodea"}]}
]
}
On a BarChart, one of the columns (the second one) has to be a number. That can cause this error message.
In your drawChart() function, you are probably using google.visualization.arrayToDataTable, and this does not allow any nulls. Please use addColumn function explicitly
If the Data format should be like:
data: [
["string", "string"], //first Column
["string1", number],
["string2", number],
["string3", number],
]
then you can overcome this error.
when you are passing your data from controller you need to do like so: just take an example I have controller and I am sending data through it via group by.
controller:
\DB::statement("SET SQL_MODE=''");//this is the trick use it just before your query
$Rspatients = DB::table('reports')
->select(
DB::raw("day(created_at) as day"),
DB::raw("Count(*) as total_patients"))
->orderBy("created_at")
->groupBy(DB::raw("day(created_at)"))
->get();
$result_patients[] = ['day','Patients'];
foreach ($Rspatients as $key => $value) {
$result_patients[++$key] = [$value->day,$value->total_patients];
}
return view('Dashboard.index')
->with('result_patients',json_encode($result_patients,JSON_NUMERIC_CHECK));
if there is no JSON_NUMERIC_CHECK, so the data will be array of strings while if there is json check the data will be converted to array of numbers.
before JSON check data:
4: (2) ["24", "413"]
5: (2) ["25", "398"]
After JSON Check data:
4: (2) [24, 413]
5: (2) [25, 398]