20

I have a json string that is converted from object by JSON.Stringify function.

I'd like to know if it's json string or just a regular string.

Is there any function like "isJson()" to check if it's json or not?

I'd like to use the function when I use local storage like the code below.

Thank you in advance!!

var Storage = function(){}

Storage.prototype = {

  setStorage: function(key, data){

    if(typeof data == 'object'){

      data = JSON.stringify(data);
      localStorage.setItem(key, data);     

    } else {
      localStorage.setItem(key, data);
    }

  },


  getStorage: function(key){

    var data = localStorage.getItem(key);

    if(isJson(data){ // is there any function to check if the argument is json or string?

      data = JSON.parse(data);
      return data;

    } else {

      return data;
    }

  }

}

var storage = new Storage();

storage.setStorage('test', {x:'x', y:'y'});

console.log(storage.getStorage('test'));
crzyonez777
  • 1,789
  • 4
  • 18
  • 27

5 Answers5

32

The "easy" way is to try parsing and return the unparsed string on failure:

var data = localStorage[key];
try {return JSON.parse(data);}
catch(e) {return data;}
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
15

you can easily make one using JSON.parse. When it receives a not valid JSON string it throws an exception.

function isJSON(data) {
   var ret = true;
   try {
      JSON.parse(data);
   }catch(e) {
      ret = false;
   }
   return ret;
}
letiagoalves
  • 11,224
  • 4
  • 40
  • 66
6

Found this in another post How do you know if an object is JSON in javascript?

function isJSON(data) {
    var isJson = false
    try {
        // this works with JSON string and JSON object, not sure about others
       var json = $.parseJSON(data);
       isJson = typeof json === 'object' ;
    } catch (ex) {
        console.error('data is not JSON');
    }
    return isJson;
}
Community
  • 1
  • 1
Benoit Gauthier
  • 141
  • 2
  • 8
2

Since the question is "How to check if it's a string or json" maybe a simple way would be to check for string, so you would have done something like this somewhere:

    if (typeof data === 'string') { // check for string!
      //... do something
    } else {///... do something else}

Maybe that could be enough depending on your overall solution, just in case someone else is looking around.

darmis
  • 2,879
  • 1
  • 19
  • 21
0

I think returning parsed JSON at the same time is a good idea, so I prefer following version:

function tryParse(str) {
    try {
        return { value: JSON.parse(str), isValid: true }
    } catch (e) {
        return { value: str, isValid: false }
    }
}

As you probably know JSON.parse("1234"), JSON.parse("0"), JSON.parse("false") and JSON.parse("null") won't raise Exception and will return true. all this values are valid JSON but if you want to see isValid is true only for objects (e.g: { "key": "value" }) and arrays (e.g: [{ "key": "value" }]) you can use following version:

function tryParse(str) {
    try {
        var parsed = JSON.parse(str);
        return { value: parsed , isValid: typeof parsed === 'object'}
    } catch (e) {
        return { value: str, isValid: false }
    }
}
Mehdi Dehghani
  • 10,970
  • 6
  • 59
  • 64
  • `1234`, `0`, `false` and `null` are not valid JSON, those are Numbers, Boolean and Null, they are implicitly converted to String in [`JSON.parse`](https://www.ecma-international.org/ecma-262/5.1/#sec-15.12.2) . Due to that implicit conversion those values result into these Strings `"1234"`, `"0"`, `"false"` and `"null"` which are then indeed valid JSON. It is that same as if you would have `var test = {toString() {return 1}}; console.log(JSON.parse(test))`, this can also be parse and results in `1` but that would not make `test` to be valid JSON. – t.niese Mar 16 '19 at 09:35
  • For that use cases you need more code, that can not be done with 4 lines of simple code, I think we talking about regular usage here not something like `{toString() {return 1}}` – Mehdi Dehghani Mar 16 '19 at 09:46
  • My point is that for `JSON.parse(1234)` the `1234` is **not** JSON, but a Number. That Number is implicitly converted to String within the `JSON.parse` function, but that does not change the fact that `1234` is not JSON. And I added the `{toString() {return 1}}` to make it more clear, because for `JSON.parse({toString() {return 1}})` the same thing happens internally as for `JSON.parse(1234)` both are implicitly converted to a String that is valid JSON, but both of them are not JSON at the time they are passed to `JSON.parse`. – t.niese Mar 16 '19 at 09:58
  • I edited my answer, you mean `"1234"` is valid JSON but `1234` is not? – Mehdi Dehghani Mar 16 '19 at 10:04
  • Exactly. Now it is correct. If you have `var a = 1` and var `var b = "1"` then `typeof a` is `number` and `typeof b` is `string`, both `a` and `b` can be passed to `JSON.parse` and it would result in `1`, but only `b` is in this case JSON, because it is a string based representation of the number `1`. – t.niese Mar 16 '19 at 10:13
  • You have to separate the concepts of [valid JSON](https://www.json.org/) - from the idea of JSON encoded string in Javascript. For example `"1234"` and `1234` are both valid JSON, while `undefined` is not. If JS was a more sane language it would throw an error if you passed anything other than a string to JSON.parse instead of the implicit casting shenanigans. – max Mar 16 '19 at 10:17
  • Okay, now I'm confused! – Mehdi Dehghani Mar 16 '19 at 10:19
  • If you have a file `test.json` and that contents is just `"1234"` then this file holds the string with the value `1234`, the equivalent JSON representation in JavaScript would be `"\"1234\""`, because `JSON.parse("\"1234\"")` returns the `string` with the value `1234`. If the content of the file is just `1234` then this json file holds a number, the JSON representation in JS is then `"1234"` because `JSON.parse("1234")` returns the number with the value `1234`. And for `JSON.parse(1234)` JS does `JSON.parse(String(1234))`. – t.niese Mar 16 '19 at 10:24
  • https://jsonlint.com/ says both of `1234` and `"1234"`, where I can validate JSON that says `1234` is not valid JSON? – Mehdi Dehghani Mar 16 '19 at 10:27
  • It depends in which context you are, `jsonlint` validates the content of the JSON string, and not in the context of JS. So if the content of the JSON string is `1234` then this is valid JSON (a number), if the content of the JSON string is `"1234"` then this is also valid JSONB (a number) . But the `1234` in JSON has to be `"1234"` in JS because JSON has to be encoded as string, and the `"1234"` has to be `"\"1234\""`. `JSON.parse("\"1234\"")` => `string`, `JSON.parse("1234")` => `number`. And `JSON.parse(1234)` => `JSON.parse(String(1234))` => `number`. – t.niese Mar 16 '19 at 10:31
  • So, my answer before the edit was true? (_somehow_) (I mean now is more clear, but I think based on comments, before the edit was correct too, am I right? if I'm wrong, I should say I didn't get why) – Mehdi Dehghani Mar 16 '19 at 10:33
  • No it was not for `JSON.parse(1234)` the `1234` is a JavaScript primitive (a Number), and not JSON. It would be the same as if you would say that for `var a = {"foo":1, "bar": 2}` the `{"foo":1, "bar": 2}` is JSON. You can copy it to a JSON validator and it would validate, because its text representation is JSON, but in the context of JavaScript the `{"foo":1, "bar": 2}` is a JavaScript object and not JSON, because you cannot write `JSON.parse({"foo":1, "bar": 2})`. Only if you would write `var a = '{"foo":1, "bar": 2}'`, then the string `'{"foo":1, "bar": 2}'` holds JSON. – t.niese Mar 16 '19 at 10:37
  • Nice example, now I understand your point, thank you! – Mehdi Dehghani Mar 16 '19 at 11:04