Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Re: Verify syntax of large JSON files

by Loops (Curate)
on Nov 23, 2014 at 04:40 UTC ( #1108136=note: print w/replies, xml ) Need Help??

in reply to Verify syntax of large JSON files

You could use one of the JSON readers that have a streaming capability rather than loading the entire thing into memory, such as JSON::Streaming::Reader. The code below is a quick try that works here, although I don't have any multi-meg JSON files handy. Have to provide routines for each element type read in the stream; the code below just has null subs for them but doing a $jsonr->skip instead would probably speed things up even more:

use IO::File; use JSON::Streaming::Reader; sub is_valid_json { my $fh = IO::File->new(shift, "r"); my $jsonr = JSON::Streaming::Reader->for_stream($fh); my @ignore = map {($_, sub {})} qw(start_array end_array start_object add_string add_number add_boolean add_null end_object start_property end_property +); eval {$jsonr->process_tokens(@ignore, error => sub {die "@_"})}; return !$@; } print is_valid_json('file.json') ? 'ok' : 'panic';

Replies are listed 'Best First'.
Re^2: Verify syntax of large JSON files
by ron800 (Novice) on Nov 23, 2014 at 14:29 UTC
    Thanks. That seems to work on my small files. The only issue is that I can't figure out how to indicate where exactly in the JSON file the error occurs.

      Looking at JSON::Streaming::Reader, I quickly found this line:

      my $char = $self->_peek_char();

      which lead me to expect the module to be quite slow at what it does.

      Luckily, parsing JSON is quite an easy task. Just checking it for validity is even easier than that. So I quickly rolled a JSON parser that just checked validity and didn't read the whole file into RAM at once.

      So I built a 65MB file of JSON so I could compare:

      > perl < file.json Valid JSON. Took 38s. > perl okTook 446s.

      So it looks like my version is over 10x faster.

      [Update: Adding $jsonr->skip() inside the empty 'sub' as Loops suggests, makes the module run about 2x faster:

      > perl okTook 235s.

      or only about 1/6th as fast as my code.]

      Then I added an error near the end of the file:

      > perl panicTook 402s. > perl < file.json Invalid bare word (troo) at line 1020000, pos 8 (t) Took 39s.

      So you can see it also gives much better information about where the problem was.

      - tye        

        I decided I had to front-page this thread, just so more people would see your json parser. Thank you for posting this.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1108136]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2022-08-19 04:45 GMT
Find Nodes?
    Voting Booth?

    No recent polls found