简体   繁体   中英

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.

A JSON text can be any of the JSON data types.

1234

… is a valid JSON text consisting of a Number. (Passing 1234 as a number to JSON.parse works because it gets converted to a string by JavaScript's normal typecasting rules).

"Is life a valid JSON?"

… is a valid JSON text consisting of a String.

Is life a valid JSON?

… is not a valid JSON text. It is just a bunch of characters which don't match the syntax of any JSON data type.

So no. Your second function would not be right. It claims that 1234 is not valid JSON.

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 { .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM