Maaz Syed Adeeb Maaz Syed Adeeb - 1 month ago 6
JSON Question

JSON.parse on a number as a string doesn't throw error

I believed that this is one of the ways to correctly distinguish an invalid JSON object as string from a valid one



function isValidJson(s) {
try {
JSON.parse(s);
return true;
} catch (e) {
return false;
}
}

console.log(isValidJson(1234)); // true
console.log(isValidJson('1234')); // true
console.log(isValidJson('Is life a valid JSON?')); // false :(
console.log(isValidJson('{"a" : { "b": [1, 2, 3] }}')); // true





This is the most common answer I see, in regards to achieving the distinction. I don't seem to quite understand what is happening here. This snippet actually recognizes numbers and numbers as strings as valid JSON objects. Could anyone throw light on why/how this is happening?

Also, on reading the MDN docs for JSON.parse, I found the reviver method. I wrote a function which seems to work for all scenarios. Would this function actually be the right way?



function isValidJson(s) {
try {
JSON.parse(s, function(k, v) {
if (k === "" && typeof v === "number") {
throw "Invalid JSON";
}
return v;
});
return true;
} catch (e) {
return false;
}
}

console.log(isValidJson(1234)); // false
console.log(isValidJson('1234')); // false
console.log(isValidJson('Is life a valid JSON?')); // false :(
console.log(isValidJson('{"a" : { "b": [1, 2, 3] }}')); // true





[EDIT] I may have wrongly implied that I'm looking to distinguish valid JSON strings. I meant, valid JSON objects as strings. Edited the question with regards to this.

Answer

I think the case where isValidJsonString(1234) returns true is just Javascript being its usual eager self at turning things into strings at the first opportunity. If you add a check to the function that the argument is actually a string, everything is fine:

function isValidJsonString(s) {
  if (typeof s !== 'string') {
    return false;
  }
  try {
    JSON.parse(s);
    return true;
  } catch (e) {
    return false;
  }
}

The others already work as they should.

This snippet actually recognizes numbers and numbers as strings as valid JSON strings. Could anyone throw light on why/how this is happening?

It is happening because numbers as strings are valid JSON strings.

[EDIT] I may have wrongly implied that I'm looking to distinguish valid JSON strings. I meant, valid JSON objects as strings. Edited the question with regards to this.

Your current method also doesn't do that, it only excludes numbers.

JSON values can be seven different things: object (in {}), array (in []), string (in ""), number, null, false or true. Of these, you exclude only the number.

If you use typeof v !== "object", then accept only objects, arrays and null. Maybe that is what you want, maybe not.

If you only want JSON objects, just check that the first non-whitespace character in your JSON string is a {.

Comments