javabeangrinder
javabeangrinder

Reputation: 7159

Parsing faulty JSON and be able to display where the error is

This is not about how to manage or correct a faulty JSON, it is about how to explain to the user where the error is in the faulty JSON.

Is there a way to find out at which position in the JSON the parser failed.

I want to solve this problem in a node.js application so please keep your answers in that domain if possible.

When I use the built in JSON object and the parse method for a faulty JSON I only get the exception message SyntaxError: Unexpected string. I would like to find out where the error occurred.

Preferred would be a JSON.validate(json) that returned result ok/error and the error position. Something like this:

var faultyJsonToParse = '{"string":"value", "boolean": true"}';
var result = JSON.validate(faultyJsonToParse);
if (result.ok == true) {
   console.log('Good JSON, well done!');
} else {
   console.log('The validator found a \'' + result.error + '\' of type \'' + result.errorType + '\' in your JSON near position ' + result.position);
}

The wanted outcome of the above would be:

The validator found a 'SyntaxError' of type 'Unexpected string' in your JSON near position 35.

Upvotes: 16

Views: 16768

Answers (3)

david_p
david_p

Reputation: 6576

If you are using NodeJS, clarinet is a very nice event-based JSON parser that will help you generate better error messages (line and column or the error). I have build a small utility using clarinet's parser that returns:

snippet (string): the actual line where the error happened
line (number)   : the line number of the error
column (number) : the column number of the error 
message (string): the parser's error message

The code is here: https://gist.github.com/davidrapin/93eec270153d90581097

Upvotes: 2

georg
georg

Reputation: 215039

Try jsonLint:

var faultyJsonToParse = '{"string":"value", "boolean": true"}';

try {
    jsonlint.parse(faultyJsonToParse)
} catch(e) {
    document.write('<pre>' + e)
}

result:

Error: Parse error on line 1:
...ue", "boolean": true"}
-----------------------^
Expecting 'EOF', '}', ',', ']', got 'undefined'

(although jsonLint is a node project, it can also be used in web: simply grab https://github.com/zaach/jsonlint/blob/master/web/jsonlint.js)

As @eh9 suggested, it makes sense to create a wrapper around the standard json parser to provide detailed exception info:

JSON._parse = JSON.parse
JSON.parse = function (json) {
    try {
        return JSON._parse(json)
    } catch(e) {
        jsonlint.parse(json)
    }
}

JSON.parse(someJson) // either a valid object, or an meaningful exception

Upvotes: 16

eh9
eh9

Reputation: 7428

The built-in versions of JSON.parse() don't have consistent behavior. It's consistent when the argument is well-formed, and inconsistent if it's not. This goes back to an incomplete specification of this function in the original JSON library implementation. The specification was incomplete because it did not define an interface for exception objects. And this situation leads directly to your question.

While I don't know of a solution that's off-the-shelf at this time, the solution requires writing a JSON parser and tracking position information for error handling. This can be inserted seamlessly into your existing code by (1) first invoking the native version, and (2) if the native version throws an exception, invoke the position-aware version (it'll be slower) let it throw the exception that your own code standardizes on.

Upvotes: 2

Related Questions