Reading from Json File garbage after json object - json

I'm using json file in a Perl program. I'm unable to parse the json file.
It is giving following error:
garbage after JSON object, at character offset 2326471 (before "{"response":{"numFou...") at /usr/local/share/perl5/JSON.pm line 171, <$f> line 1.
Here is the code:
print "input json";
open(my $f, "<", "$ARGV[1]");
my $content=<$f>;
my $structured;
eval {
$structured = from_json($content, {utf8 => 1});
};
if ($#) {
$content =~ s/\n/ /g;
my $errMsg = $#;
$errMsg =~ s/\n/ /g;
WriteInfo("Unparseable result for url=$url, error: $errMsg\n") ;
};
How can I fix this error?

How can I fix this error?
You can't fix JSON data automatically. There could be many "fixes" that will get the data through the parser, but it may be difficult to tell which of them is the correct one. You should talk to the source of the data and ask for a correct version
It may be possible to fix the data manually, but you should only attempt this if there is no correct version of the data available. Finding the error in a 2.2MB+ text file by hand isn't a trivial job, and the character position 2326471 is only where the parser found an error, not where the correction should be made
garbage after JSON object ...
This implies that from_json has found the end of the JSON data -- i.e. the final closing brace } or bracket ] -- but there is data in the string after that character. It may be that the file has been written correctly, but there really is spurious data after the end of the JSON. If so then that should be obvious just by examining the data file
Note
Unless you have redefined the $/ variable, these lines
open(my $f, "<", "$ARGV[1]");
my $content = <$f>;
will read just the first line of the file into $content. It may be that the file contains just a single very long line of tex (i.e. it contains no newline characters) but this line in your error handler
$content =~ s/\n/ /g;
implies that ther are newlines in there.
Reading only the first line of a multi-line JSON file wouldn't cause the error that you're seeing, but it is best to read the entire file into memory before decoding it as JSON data, just in case unexpected newlines have crept into the data
Here is a better way of writing your code segment
print "Input JSON\n";
my $content - do {
open my $fh, '<', $ARGV[1] or die qq{Unable to open "$ARGV[1]" for input: $!};
local $/;
<$fh>;
};
my $structured = eval {
from_json( $content, {utf8 => 1} );
};
if ( my $err_msg = $# ) {
$content =~ tr/\n/ /;
$err_msg =~ tr/\n/ /;
WriteInfo("Unparsable result for URL=$url, error: $err_msg\n") ;
};

Related

How do I use encode_json with string in Perl?

Here is my code that I try to open the file to get data and change it to UTF-8, then read each line and store it in variable my $abstract_text and send it back in JSON structure.
my $fh;
if (!open($fh, '<:encoding(UTF-8)',$path))
{
returnApplicationError("Cannot read abstract file: $path ($!)\nERRORCODE|111|\n");
}
printJsonHeader;
my #lines = <$fh>;
my $abstract_text = '';
foreach my $line (#lines)
{
$abstract_text .= $line;
}
my $json = encode_json($abstract_text);
close $fh;
print $json;
By using that code, I get this error;
hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)
error message also point out that the problem is in this line;
my $json = encode_json($abstract_text);
I want to send the data back as a string (which is in UTF-8). Please help.
I assume you're using either JSON or JSON::XS.
Both allow for non-reference data, but not via the procedural encode_json routine.
You'll need to use the object-oriented approach:
use strict; # obligatory
use warnings; # obligatory
use JSON::XS;
my $encoder = JSON::XS->new();
$encoder->allow_nonref();
print $encoder->encode('Hello, world.');
# => "Hello, world."

how to decode json in perl if value has \n or more than one line

how to decode the json file if a value has more than one line
a.json file:
{
"sv1" : {
"output" : "Hostname: abcd
asdkfasfjsl",
"exp_result" : "xyz"
}
}
when I try to read the above json file, I am hitting with an error "invalid character encountered while parsing JSON string, at character offset 50 (before "\n ...")"
code to read the above json file:
#!/volume/perl/bin/perl -w
use strict;
use warnings;
use JSON;
local $/;
open(AA,"<a.json") or die "can't open json file : $!\n";
my $json = <AA>;
my $data = decode_json($json);
print "reading output $data->{'sv1'}->{'output'}\n";
print "reading output $data->{'sv1'}->{'exp_result'}\n";
close AA;
Besides from whether the JSON is valid or not (see comments on question), you're reading only the first line from the file.
my $json = <AA>;
This is a scalar variable and receives only one line.
Use an array to get all lines:
my #json = <AA>;
my $json = join "\n", #json;
or even better: use File::Slurp::read_file to get the whole content of the file with one simple command.
use File::Slurp qw/read_file/;
my $json = read_file( "a.json" );

JSON parsing error in perl

I get the error
EXECUTION FAILED ...malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)")"
when I parse my JSON string from DB to this snippet.
my $json_geno1 = decode_json($geno_set_one);
warn Dumper($json_geno1);
Am I missing something ? The json string is from the Database.
$VAR1 = [
'{"":"No Call","rs1032807":"AG","rs718757":"AG","rs6557634":"CC","rs995553":"CG","rs6166":"AG","rs4925":"AA","rs502843":"GT","rs725029":"No Call","rs3904872":"GG","rs1402695":"TT","rs719601":"AA","rs2374061":"AG","rs952503":"TT","rs1801262":"AG","rs5215":"CT","rs978422":"CC","rs12828016":"GG","rs958388":"AG","rs999072":"CT","rs967344":"AG","rs2207782":"CC","rs349235":"AA","rs1074553":"CT","rs1395936":"AG","GS35220":"CT","rs7627615":"AG","rs727336":"AG","rs2077774":"AC","rs8065080":"CC","rs1131498":"TT","rs2247870":"No Call","rs803172":"TT","rs1541290":"AG","rs1414904":"AA","rs1928045":"No Call","rs2077743":"GT","rs2361128":"No Call","rs3795677":"AG","rs1030687":"CT","rs156318":"GG","rs952768":"CC","rs1363333":"TT","rs7298565":"AG","rs310929":"CC","rs2369898":"CT","rs1327118":"CC","rs4619":"AG","rs965323":"TT","rs2887851":"AG","rs1862456":"GT","rs6759892":"GT","rs753381":"AG","rs1805034":"CC","rs1812642":"AA","rs4075254":"CT","rs1805087":"AA","rs532841":"CT","rs951629":"GG","rs2286963":"GG","rs763553":"CT","rs1074042":"GG","rs2241714":"GG","rs894240":"TT","rs522073":"CT","GS35205":"TC","rs1368136":"TT","rs1426003":"GG","rs2016588":"No Call","rs621277":"No Call","rs727081":"GG","rs1392265":"AC","rs1079820":"No Call","rs4843075":"AG","rs156697":"CC","rs11096957":"AC","rs1952161":"GG","rs1961416":"AG","rs1585676":"GG","rs890910":"TT","rs171953":"AG","rs1843026":"CC","rs1515002":"CC","rs756497":"No Call","rs1293153":"No Call","rs754257":"GT","rs649058":"AG","rs726957":"AG","rs728189":"No Call","GS34251":"TC","rs3742207":"No Call","rs210310":"CT","rs2216629":"AG","rs1541836":"CT","rs722952":"CT","rs1105176":"GG"}'
];
Thanks
You should probably use:
my $json_geno1 = decode_json($VAR1[0]);
because $VAR1 is now an array.
This JSON is valid (I've tested it in PHP) and I get object from this string without a problem.
I got exactly same error. Which got resolved by removing for below code
my $json;
{
local $/;
open ($fh, "+<temp.json") or die $!;
my $json = <$fh>;
close $fh;
}
and got resolved by removing the my from line number 5.
my $json;
{
local $/;
open ($fh, "+<temp.json") or die $!;
$json = <$fh>;
close $fh;
}
I got this* msg too, when i tried to call the read function like this:
perl json_read_test.pl /server/lib/Schema/user_data.schema.json
When I used it with ./ or without / or with full path name, that solved the problem.
**
"malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "(end of string)") at /usr/share/perl5/JSON.pm line 190."
my $json_geno1 = decode_json($geno_set_one->[0]);
warn Dumper($json_geno1);

Delete one character at End of File in PERL

So I have encountered a problem while programming with PERL. I use a foreach loop to get some data out of the hash, so it has to loop through it.
The Code:
foreach $title (keys %FilterSPRINTHASH) {
$openSP = $FilterSPRINTHASH{$title}{openSP};
$estSP = $FilterSPRINTHASH{$title}{estSP};
$line = "'$title':{'openSP' : $openSP, 'estSP' : $estSP}\n";
print $outfile "$line\n";
}
The thing is, that I am creating a seperate File with the PERL's writting to a file expression, which will be a JSONP text (later used for HTML).
Back to the problem:
As JSONP requires comma's "," after every line that is not the last one, i had to put a comma at the end of line, however when the last line comes in, I have to remove the comma.
I have tried with CHOP function, but not sure where to put it, since if I put it at the end of foreach, it will just chop the comma in $line, but this wont chop it in the new file I created.
I have also tried with while (<>) statement, with no success.
Any ideas appreaciated.
BR
Using JSON module is far less error prone; no need to reinvent the wheel
use JSON;
print $outfile encode_json(\%FilterSPRINTHASH), "\n";
You can check if it is the last iteration of the loop, then remove the comma from line.
So something like
my $count = keys %FilterSPRINTHASH; #Get number of keys (scalar context)
my $loop_count = 1; #Use a variable to count number of iteration
foreach $title (keys %FilterSPRINTHASH){
$openSP = $FilterSPRINTHASH{$title}{openSP};
$estSP = $FilterSPRINTHASH{$title}{estSP};
$line = "'$title':{'openSP' : $openSP, 'estSP' : $estSP}\n";
if($loop_count == $count){
#this is the last iteration, so remove the comma from line
$line =~ s/,+$//;
}
print $outfile "$line\n";
$loop_count++;
}
i would approach this by storing your output in an array and then joining that with the line separators you wish:
my #output; # storage for output
foreach $title (keys %FilterSPRINTHASH) {
# create each line
my $line = sprintf "'%s':{'openSP' : %s, 'estSP' : %s}", $title, $FilterSPRINTHASH{$title}{openSP}, $FilterSPRINTHASH{$title}{estSP};
# and put it in the output container
push #output, $line;
}
# join all outputlines with comma and newline and then output
print $outfile (join ",\n", #output);

I am converting a json file returned from the server into perl data structures

I am able to convert a hard coded json string into perl hashes however if i want to convert a complete json file into perl data structures which can be parsed later in any manner, I am getting the folloring error.
malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)") at json_vellai.pl line 9
use JSON::PP;
$json= JSON::PP->new()
$json = $json->allow_singlequote([$enable]);
open (FH, "jsonsample.doc") or die "could not open the file\n";
#$fileContents = do { local $/;<FH>};
#fileContents = <FH>;
#print #fileContents;
$str = $json->allow_barekey->decode(#filecontents);
foreach $t (keys %$str)
{
print "\n $t -- $str->{$t}";
}
This is how my code looks .. plz help me out
It looks to me like decode doesn't want a list, it wants a scalar string.
You could slurp the file:
undef $/;
$fileContents = <FH>;