1486

Given a string of JSON data, how can I safely turn that string into a JavaScript object?

Obviously I can do this unsafely with something like:

var obj = eval("(" + json + ')');

but that leaves me vulnerable to the JSON string containing other code, which it seems very dangerous to simply eval.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
Matt Sheppard
  • 116,545
  • 46
  • 111
  • 131
  • 86
    In most languages eval carries an additional risk. Eval leaves an open door to be exploited by hackers. HOWEVER, remember that all javascript runs on the client. *EXPECT* that it will be changed by hackers. They can EVAL anything they want, just by using the console. You must build your protection on the server side. – Beachhouse Feb 07 '13 at 17:34
  • 24
    Ok, now it is 2014 and you should never use `eval` in order to parse a JSON string because you would be exposing your code to "code injection". Use `JSON.parse(yourString)` instead. – Daniel Oct 22 '14 at 06:27
  • 1
    Is the JSON data a literal ? – shanechiu Sep 25 '17 at 10:02
  • 1
    @shanechiu: if you mean a scalar data type, yes it is. Is just a string with a key-value syntax in it. – 0zkr PM Sep 17 '18 at 18:09
  • 1
    See the documentation on the `parse()` method: https://www.w3schools.com/js/js_json_parse.asp – Ale Gu Jul 17 '20 at 20:56

28 Answers28

2110

JSON.parse(jsonString) is a pure JavaScript approach so long as you can guarantee a reasonably modern browser.

Graham
  • 3,153
  • 3
  • 16
  • 31
Jonathan.
  • 53,997
  • 54
  • 186
  • 290
  • 79
    I'm pretty sure it's safe for Node.js – Stephen Oct 18 '11 at 17:07
  • 3
    It isn't supported in all browsers, but the script at the link below adds it to browsers that don't have it: https://github.com/douglascrockford/JSON-js/blob/master/json2.js – speedplane Jan 12 '13 at 05:53
  • 6
    [Pretty safe to use](http://stackoverflow.com/questions/891299/browser-native-json-support-window-json). – Redsandro Oct 08 '13 at 11:52
  • 14
    If you are doing NodeJS, there is no way I would load up jQuery just to parse a jsonString into a JSON object. So upvote Jonathan's answer – Antony Oct 15 '13 at 16:49
  • unsupported by IE8, some versions of IE9, & older versions of all other browsers – Alex V May 04 '14 at 14:34
  • Indeed JSON is not in every browser and was added recently. For some browsers to support JSON you need to load external library for example: https://github.com/douglascrockford/JSON-js – Grzegorz May 27 '14 at 11:08
  • 6
    According to [**this link**](http://caniuse.com/#search=JSON.parse) it is supported by IE8+, although it says: `Requires document to be in IE8+ standards mode to work in IE8.` – JoshuaDavid Jan 12 '15 at 21:19
  • 1
    Unless you're absolutely sure about the source of the json, it never hurts to have a try/catch block to handle scenarios where the json is invalid. – GMchris Jan 28 '16 at 12:19
  • 2
    I think it's worth mentioning here that it would be a good idea to handle a failure gracefully by adding a `try{} catch(e){}` – JaeGeeTee Sep 28 '17 at 14:46
  • Is it really safe from user-provided content? Could this result in a script-injection attack, e.g. if jsonString is `'{"color": "deep purple"}'`? – prototype Aug 17 '18 at 03:16
  • 1
    @prototype Yes, it is safe, why wouldn't it be? It's a JSON parser, not a script interpreter. – Armen Michaeli Nov 15 '19 at 09:57
  • 1
    @amn you're right that `JSON.parse(str)` is itself safe. At the time of my original comment, my context was if that snippet exists inside a – prototype Nov 17 '19 at 18:09
902

The jQuery method is now deprecated. Use this method instead:

let jsonObject = JSON.parse(jsonString);

Original answer using deprecated jQuery functionality:

If you're using jQuery just use:

jQuery.parseJSON( jsonString );

It's exactly what you're looking for (see the jQuery documentation).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
Alex V
  • 18,176
  • 5
  • 36
  • 35
  • 9
    Is there a reason to use this over JSON.parse()? – Jon Mar 20 '16 at 02:02
  • 10
    `jQuery.parseJSON` defaults to using `JSON.parse` if it exists, so the only reason to use this over the real one is if you need a fallback for – Karl-Johan Sjögren Apr 05 '16 at 20:49
  • 13
    2016 update: As of jQuery 3.0, [$.parseJSON](https://api.jquery.com/jQuery.parseJSON/) is deprecated and you should use the native JSON.parse method instead. – jkdev Jun 28 '16 at 22:36
169

This answer is for IE < 7, for modern browsers check Jonathan's answer above.

This answer is outdated and Jonathan's answer above (JSON.parse(jsonString)) is now the best answer.

JSON.org has JSON parsers for many languages including four different ones for JavaScript. I believe most people would consider json2.js their goto implementation.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
John
  • 14,944
  • 12
  • 57
  • 57
80

Use the simple code example in "JSON.parse()":

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);

and reversing it:

var str = JSON.stringify(arr);
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Ronald Coarite
  • 4,460
  • 27
  • 31
27

This seems to be the issue:

An input that is received via Ajax websocket etc, and it will be in String format, but you need to know if it is JSON.parsable. The touble is, if you always run it through JSON.parse, the program MAY continue "successfully" but you'll still see an error thrown in the console with the dreaded "Error: unexpected token 'x'".

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Cody
  • 9,785
  • 4
  • 61
  • 46
  • NO. The issue is that you are expecting a JSON object and could end up with `(function(){ postCookiesToHostileServer(); }());` or even nastier stuff in the context of Node. – Yaur Apr 15 '14 at 21:56
  • Well JSON.parse scrubs the input of functions (which in this case would not help as its an IIF --> object). It seems the best way to go about this subject is try/catch. (See edit) – Cody Apr 24 '14 at 21:11
25

I'm not sure about other ways to do it but here's how you do it in Prototype (JSON tutorial).

new Ajax.Request('/some_url', {
  method:'get',
  requestHeaders: {Accept: 'application/json'},
  onSuccess: function(transport){
    var json = transport.responseText.evalJSON(true);
  }
});

Calling evalJSON() with true as the argument sanitizes the incoming string.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Mark Biek
  • 146,731
  • 54
  • 156
  • 201
21

If you're using jQuery, you can also use:

$.getJSON(url, function(data) { });

Then you can do things like

data.key1.something
data.key1.something_else

etc.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Leanan
  • 732
  • 7
  • 13
19

Just for fun, here is a way using a function:

 jsonObject = (new Function('return ' + jsonFormatData))()
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
lessisawesome
  • 1,313
  • 1
  • 12
  • 14
  • 3
    Interesting approach, I'm not sure I'd use this with JSON.Parse available, but it's nice to see someone thinking outside of the box. –  Sep 03 '15 at 10:58
  • 7
    This is very similar to just using `eval` to do it and isn't safe. :P – Nebula Nov 07 '15 at 12:18
  • 10
    This has all the drawbacks of using `eval` but is more complicated and harder for maintainers to understand. – Quentin Nov 24 '15 at 15:06
18

Using JSON.parse is probably the best way.

Here's an example

var jsonRes = '{ "students" : [' +
          '{ "firstName":"Michel" , "lastName":"John" ,"age":18},' +
          '{ "firstName":"Richard" , "lastName":"Joe","age":20 },' +
          '{ "firstName":"James" , "lastName":"Henry","age":15 } ]}';
var studentObject = JSON.parse(jsonRes);
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Barath Kumar
  • 439
  • 3
  • 7
17
$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: callback
});

The callback is passed the returned data, which will be a JavaScript object or array as defined by the JSON structure and parsed using the $.parseJSON() method.

hexacyanide
  • 88,222
  • 31
  • 159
  • 162
Prahlad
  • 364
  • 3
  • 6
10

Try using the method with this Data object. ex:Data='{result:true,count:1}'

try {
  eval('var obj=' + Data);
  console.log(obj.count);
}
catch(e) {
  console.log(e.message);
}

This method really helps in Nodejs when you are working with serial port programming

GPrathap
  • 7,336
  • 7
  • 65
  • 83
  • It is really funny how people are fixated to "eval is evil" and they'll do anything to avoid it, even re-writing the whole eval-functionality.. – diynevala Sep 12 '14 at 10:52
  • Is consensus this trick is a safe method turning string into JSON object? I could use this as no additional js imports are needed. – Whome Oct 13 '14 at 10:48
  • 1
    **ANY** approach using `eval` or `Function` is equally vulnerable – Slai Jun 03 '18 at 12:32
  • 1
    `undefined; function bye() {...} bye();` – Salvioner Jan 22 '19 at 12:41
10

The easiest way using parse() method:

var response = '{"result":true,"count":1}';
var JsonObject= JSON.parse(response);

Then you can get the values of the JSON elements, for example:

var myResponseResult = JsonObject.result;
var myResponseCount = JsonObject.count;

Using jQuery as described in the jQuery.parseJSON() documentation:

JSON.parse(jsonString);
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Jorgesys
  • 124,308
  • 23
  • 334
  • 268
5

I found a "better" way:

In CoffeeScript:

try data = JSON.parse(jqxhr.responseText)
data ||= { message: 'Server error, please retry' }

In Javascript:

var data;

try {
  data = JSON.parse(jqxhr.responseText);
} catch (_error) {}

data || (data = {
  message: 'Server error, please retry'
});
Dorian
  • 22,759
  • 8
  • 120
  • 116
5

JSON parsing is always a pain. If the input is not as expected it throws an error and crashes what you are doing.

You can use the following tiny function to safely parse your input. It always turns an object even if the input is not valid or is already an object which is better for most cases:

JSON.safeParse = function (input, def) {
  // Convert null to empty object
  if (!input) {
    return def || {};
  } else if (Object.prototype.toString.call(input) === '[object Object]') {
    return input;
  }
  try {
    return JSON.parse(input);
  } catch (e) {
    return def || {};
  }
};
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Tahsin Turkoz
  • 4,356
  • 1
  • 27
  • 18
  • `Object.prototype.toString.call(input) === '[object Object]'` should be `typeof input === 'object'` IMO – Serge K. Dec 06 '17 at 16:16
  • typeof input returns object for null and arrays as well. So it is not the safe way of doing this. – Tahsin Turkoz Jan 09 '18 at 20:13
  • You already covered the `null` case before, and an array *is* an Object. If you want to test it, you can use `instanceof`. Moreover, if you give this function an `Array`, it will catch and `return def` when it could have returned the perfectly fine array. – Serge K. Jan 10 '18 at 08:56
  • My comment was about a common sense while catching objects. My function can have several preventions but using typeof input is not the preferred way of detecting objects in general. – Tahsin Turkoz Jan 10 '18 at 09:30
  • IMO, common sense doesn't use `toString()` method to check wether a variable is an object or not. See [AngularJS](https://github.com/angular/angular.js/blob/e13eeabd7e34a78becec06cfbe72c23f2dcb85f9/lib/promises-aplus/promises-aplus-test-adapter.js#L16), [jQuery](https://github.com/jquery/jquery/blob/6c38ebbd47c6b0fa654733819bd5ae36c1ac6c48/src/core.js#L262), [Underscore](https://github.com/jashkenas/underscore/blob/a9432276b90bd23d3022deb89ac1ba6b10ee7495/test/vendor/qunit-extras.js#L98), or even [devs](https://stackoverflow.com/questions/8511281/check-if-a-value-is-an-object-in-javascript) – Serge K. Jan 10 '18 at 13:34
  • It works, there's no doubt. But what if a strange library overrides `toString` ? It feels unreliable to me to rely on string representation of the object to make this kind of test. You're using a particuliar case of the `toString` representation to check wether it's an object or not. But what if you want to improve your function and test if it's an array ? Would you use `toString` along with `substring` ? – Serge K. Jan 10 '18 at 13:44
  • Hmm interesting case. It would be somehow even if it is a tiny chance. However still thinking this is safer way of distinguishing objects from arrays since typeof fails even with null value. – Tahsin Turkoz Jan 10 '18 at 19:08
5

Parse the JSON string with JSON.parse(), and the data becomes a JavaScript object:

JSON.parse(jsonString)

Here, JSON represents to process JSON dataset.

Imagine we received this text from a web server:

'{ "name":"John", "age":30, "city":"New York"}'

To parse into a JSON object:

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}'); 

Here obj is the respective JSON object which looks like:

{ "name":"John", "age":30, "city":"New York"}

To fetch a value use the . operator:

obj.name // John
obj.age //30

Convert a JavaScript object into a string with JSON.stringify().

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Amitesh Bharti
  • 14,264
  • 6
  • 62
  • 62
4

JSON.parse() converts any JSON string passed into the function into a JSON object.

To understand it better, press F12 to open "Inspect Element" in your browser and go to the console to write the following commands:

var response = '{"result":true,"count":1}'; //sample json object(string form)
JSON.parse(response); //converts passed string to JSON Object.

Now run the command:

console.log(JSON.parse(response));

You'll get output as an Object {result: true, count: 1}.

In order to use that Object, you can assign it to the variable, maybe obj:

var obj = JSON.parse(response);

By using obj and the dot (.) operator you can access properties of the JSON object.

Try to run the command:

console.log(obj.result);
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Pushkar Kathuria
  • 331
  • 2
  • 17
4
JSON.parse(jsonString);

json.parse will change into object.

Shekhar Tyagi
  • 1,644
  • 13
  • 18
4

Official documentation:

The JSON.parse() method parses a JSON string, constructing the JavaScript value or object described by the string. An optional reviver function can be provided to perform a transformation on the resulting object before it is returned.

Syntax:

JSON.parse(text[, reviver])

Parameters:

text : The string to parse as JSON. See the JSON object for a description of JSON syntax.

reviver (optional) : If a function, this prescribes how the value originally produced by parsing is transformed, before being returned.

Return value

The Object corresponding to the given JSON text.

Exceptions

Throws a SyntaxError exception if the string to parse is not valid JSON.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Salomon Zhang
  • 1,553
  • 3
  • 23
  • 41
3

If we have a string like this:

"{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"

then we can simply use JSON.parse twice to convert this string to a JSON object:

var sampleString = "{\"status\":1,\"token\":\"65b4352b2dfc4957a09add0ce5714059\"}"
var jsonString= JSON.parse(sampleString)
var jsonObject= JSON.parse(jsonString)

And we can extract values from the JSON object using:

// instead of last JSON.parse:
var { status, token } = JSON.parse(jsonString);

The result will be:

status = 1 and token = 65b4352b2dfc4957a09add0ce5714059
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Hamid Araghi
  • 434
  • 4
  • 15
3

Performance

There are already good answer for this question, but I was curious about performance and today 2020.09.21 I conduct tests on MacOs HighSierra 10.13.6 on Chrome v85, Safari v13.1.2 and Firefox v80 for chosen solutions.

Results

  • eval/Function (A,B,C) approach is fast on Chrome (but for big-deep object N=1000 they crash: "maximum stack call exceed)
  • eval (A) is fast/medium fast on all browsers
  • JSON.parse (D,E) are fastest on Safari and Firefox

enter image description here

Details

I perform 4 tests cases:

  • for small shallow object HERE
  • for small deep object HERE
  • for big shallow object HERE
  • for big deep object HERE

Object used in above tests came from HERE

let obj_ShallowSmall = {
  field0: false,
  field1: true,
  field2: 1,
  field3: 0,
  field4: null,
  field5: [],
  field6: {},
  field7: "text7",
  field8: "text8",
}

let obj_DeepSmall = {
  level0: {
   level1: {
    level2: {
     level3: {
      level4: {
       level5: {
        level6: {
         level7: {
          level8: {
           level9: [[[[[[[[[['abc']]]]]]]]]],
  }}}}}}}}},
};

let obj_ShallowBig = Array(1000).fill(0).reduce((a,c,i) => (a['field'+i]=getField(i),a) ,{});


let obj_DeepBig = genDeepObject(1000);



// ------------------
// Show objects
// ------------------

console.log('obj_ShallowSmall:',JSON.stringify(obj_ShallowSmall));
console.log('obj_DeepSmall:',JSON.stringify(obj_DeepSmall));
console.log('obj_ShallowBig:',JSON.stringify(obj_ShallowBig));
console.log('obj_DeepBig:',JSON.stringify(obj_DeepBig));




// ------------------
// HELPERS
// ------------------

function getField(k) {
  let i=k%10;
  if(i==0) return false;
  if(i==1) return true;
  if(i==2) return k;
  if(i==3) return 0;
  if(i==4) return null;
  if(i==5) return [];
  if(i==6) return {};  
  if(i>=7) return "text"+k;
}

function genDeepObject(N) {
  // generate: {level0:{level1:{...levelN: {end:[[[...N-times...['abc']...]]] }}}...}}}
  let obj={};
  let o=obj;
  let arr = [];
  let a=arr;

  for(let i=0; i<N; i++) {
    o['level'+i]={};
    o=o['level'+i];
    let aa=[];
    a.push(aa);
    a=aa;
  }

  a[0]='abc';
  o['end']=arr;
  return obj;
}

Below snippet presents chosen solutions

// src: https://stackoverflow.com/q/45015/860099
function A(json) {
  return eval("(" + json + ')');
}

// https://stackoverflow.com/a/26377600/860099
function B(json) {
  return (new Function('return ('+json+')'))()
}


// improved https://stackoverflow.com/a/26377600/860099
function C(json) {
  return Function('return ('+json+')')()
}

// src: https://stackoverflow.com/a/5686237/860099
function D(json) {
  return JSON.parse(json);
}

// src: https://stackoverflow.com/a/233630/860099
function E(json) {
  return $.parseJSON(json)
}



 
// --------------------
// TEST
// --------------------

let json = '{"a":"abc","b":"123","d":[1,2,3],"e":{"a":1,"b":2,"c":3}}';

[A,B,C,D,E].map(f=> {  
  console.log(
    f.name + ' ' + JSON.stringify(f(json))
  )})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This shippet only presents functions used in performance tests - it not perform tests itself!

And here are example results for chrome

enter image description here

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
2

Converting the object to JSON, and then parsing it, works for me, like:

JSON.parse(JSON.stringify(object))
Sebyddd
  • 4,305
  • 2
  • 39
  • 43
2

The recommended approach to parse JSON in JavaScript is to use JSON.parse()

Background

The JSON API was introduced with ECMAScript 5 and has since been implemented in >99% of browsers by market share.

jQuery once had a $.parseJSON() function, but it was deprecated with jQuery 3.0. In any case, for a long time, it was nothing more than a wrapper around JSON.parse().

Example

const json = '{ "city": "Boston", "population": 500000 }';
const object = JSON.parse(json);
console.log(object.city, object.population);

Browser Compatibility

Is JSON.parse supported by all major browsers?

Pretty much, yes (see reference).

samnoon
  • 1,340
  • 2
  • 13
  • 23
1

You also can use reviver function to filter.

var data = JSON.parse(jsonString, function reviver(key, value) {
   //your code here to filter
});

For more information read JSON.parse.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Durgpal Singh
  • 11,481
  • 4
  • 37
  • 49
1

Older question, I know, however nobody notice this solution by using new Function(), an anonymous function that returns the data.


Just an example:

 var oData = 'test1:"This is my object",test2:"This is my object"';

 if( typeof oData !== 'object' )
  try {
   oData = (new Function('return {'+oData+'};'))();
  }
  catch(e) { oData=false; }

 if( typeof oData !== 'object' )
  { alert( 'Error in code' ); }
 else {
        alert( oData.test1 );
        alert( oData.test2 );
      }

This is a little more safe because it executes inside a function and do not compile in your code directly. So if there is a function declaration inside it, it will not be bound to the default window object.

I use this to 'compile' configuration settings of DOM elements (for example the data attribute) simple and fast.

Codebeat
  • 6,501
  • 6
  • 57
  • 99
1

Summary:

Javascript (both browser and NodeJS) have a built in JSON object. On this Object are 2 convenient methods for dealing with JSON. They are the following:

  1. JSON.parse() Takes JSON as argument, returns JS object
  2. JSON.stringify() Takes JS object as argument returns JSON object

Other applications:

Besides for very conveniently dealing with JSON they have can be used for other means. The combination of both JSON methods allows us to make very easy make deep clones of arrays or objects. For example:

let arr1 = [1, 2, [3 ,4]];
let newArr = arr1.slice();

arr1[2][0] = 'changed'; 
console.log(newArr); // not a deep clone

let arr2 = [1, 2, [3 ,4]];
let newArrDeepclone = JSON.parse(JSON.stringify(arr2));

arr2[2][0] = 'changed'; 
console.log(newArrDeepclone); // A deep clone, values unchanged
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
1

Just to the cover parse for different input types

Parse the data with JSON.parse(), and the data becomes a JavaScript object.

var obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');

When using the JSON.parse() on a JSON derived from an array, the method will return a JavaScript array, instead of a JavaScript object.

var myArr = JSON.parse(this.responseText);
console.log(myArr[0]);

Date objects are not allowed in JSON. For Dates do somthing like this

var text = '{ "name":"John", "birth":"1986-12-14", "city":"New York"}';
var obj = JSON.parse(text);
obj.birth = new Date(obj.birth);

Functions are not allowed in JSON. If you need to include a function, write it as a string.

var text = '{ "name":"John", "age":"function () {return 30;}", "city":"New York"}';
var obj = JSON.parse(text);
obj.age = eval("(" + obj.age + ")");
MOnkey
  • 751
  • 6
  • 13
0

Another option

const json = '{ "fruit": "pineapple", "fingers": 10 }'
let j0s,j1s,j2s,j3s
console.log(`{ "${j0s="fruit"}": "${j1s="pineapple"}", "${j2s="fingers"}": ${j3s="10"} }`)
-4

Try this. This one is written in typescript.

export function safeJsonParse(str: string) {
    try {
        return JSON.parse(str);
    } catch (e) {
        return str;
    }
}
bdkopen
  • 494
  • 1
  • 6
  • 16
Supun Dharmarathne
  • 1,138
  • 1
  • 10
  • 19