I am familiar with the decode_json()
function which attempts to decode a JSON string, and terminates the Perl program with error if it fails to do so—but this question is not about that function.
What I want to do is this—I want a function through which I can run a JSON string and the function will simply tell me whether or not the JSON string is kosher—and if it isn't kosher, give me detailed information what is wrong with it.
Is there a function like this? If so, can someone here just point me in the right direction?
The function does not need to decode the JSON string—it just needs to inform the calling program if the JSON string can be decoded—and allow the calling program to continue it's run regardless of the outcome.
If something is wrong with the string - I need to know more than just what kind of error it is, but where in the string that error is—including what line number if the string is to be interpreted as the full-contents of a file. In short, information that is useful for debugging the JSON file that the string was read from.
decode_json()
croaks on error. You can catch that error by wrapping in an eval
or using Try::Tiny, if you need to use the data programmatically. The croak error message shows where the json parser failed.
$perl_scalar = decode_json $json_text
The opposite of encode_json: expects an UTF-8 (binary) string and tries to parse that as an UTF-8 encoded JSON text, returning the resulting reference. Croaks on error.
http://search.cpan.org/~mlehmann/JSON-XS-3.01/XS.pm#FEATURES
#!/usr/bin/env perl
use JSON qw(decode_json);
my $maybe_json = '{"foo":"bar", "baz"}'; # invalid, baz key is missing value
my $json_out = eval { decode_json($maybe_json) };
if ($@)
{
print "decode_json failed, invalid json. error:$@\n";
}
produces:
decode_json failed, invalid json. error:':' expected, at character offset 19 (before "}") at ./foo.pl line 6.
Deciphering the decode failure message can be frustratingly difficult.
This one is easy, because we know it is caused by a key without a value, so the parser complains that it didn't find the :
it expected at char 19. It also adds the useful 'before "}"' message to help the human interpret the error.
It might be nice to have a way to automatically parse the error message and show a larger chunk of the input string.
Let's take a quick python diversion, does that json parser provide a more useful error? Nope, it just shows char 19 without even the "before }" context.
>>> import json
>>> maybe_json = '{"foo":"bar", "baz"}'
>>> json.loads(maybe_json)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/andrew/anaconda/lib/python2.7/json/__init__.py", line 338, in loads
return _default_decoder.decode(s)
File "/Users/andrew/anaconda/lib/python2.7/json/decoder.py", line 365, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/Users/andrew/anaconda/lib/python2.7/json/decoder.py", line 381, in raw_decode
obj, end = self.scan_once(s, idx)
ValueError: Expecting : delimiter: line 1 column 20 (char 19)
So, what's the final answer? The json parser specification is pretty simple and in case of error just quits. Call the parser, if it succeeds the string was valid, else show the user where it died and ask what to do. Perl's json parser also allows options for a more relaxed translation, like interpreting single quotes (illegal) as double quotes (valid). See relaxed
and allow_singlequote
options.
Maybe you do want a linter?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With