30

I want to convert below string to an array in javascript.

{a:12, b:c, foo:bar}

How do I convert this string into array of objects? Any cool idea?

Zeck
  • 6,433
  • 21
  • 71
  • 111
  • 2
    What would this array look like? – Nick Craver Aug 13 '10 at 03:15
  • 1
    That look much like JSON. That is at its own already much like an associative array and can be accessed as such. Are you aware of this? [Look here](http://www.hunlock.com/blogs/Mastering_JSON_(_JavaScript_Object_Notation_%29). – BalusC Aug 13 '10 at 03:17
  • It's not an array. It's a single string. I just get this string from tag attribute. And i want to convert this string to an array. – Zeck Aug 13 '10 at 03:19
  • 2
    what they saying is that objects function much like arrays in javascript, and the example you have provided would in fact create a javascript object if you were to enclose the keys/values in single quotes and use `toJSON` on it. – prodigitalson Aug 13 '10 at 03:28
  • I'm assuming you mean `{a: 12, b: "c", foo: "bar"}` ... unless `c` and `bar` are actually variables in the current scope, not strings. – Anthony Mills Sep 01 '10 at 22:40

7 Answers7

84

I think that the best way of doing this, as Douglas Crockford (one of the biggests gurus of JavaScript) suggests in here is using the JSON native parser, as it is not only faster than the eval(), it's also more secure.

Native JSON parser is already available in:

  • Firefox 3.5+
  • IE 8+
  • Opera 10.5+
  • Safari Safari 4.0.3+
  • Chrome (don't know which version)

And Crockford has made a safe fallback in javascript, called json2.js, which is an adaption of the eval() approach, with some security bits added and with the native JSON parsers API. You just need to include that file, remove its first line, and use the native JSON parser, and if it's not present json2 would do the work.

Here is an example:

var myJSONString = '{ "a": 1, "b": 2 }',
    myObject = JSON.parse(myJSONString);

Once parsed you'll get an object with attributes a and b, and as you may know, you can treat an object as a hash table or associative array in JavaScript, so you would be able to access the values like this:

myObject['a'];

If you just want a simple array and not an associative one you could do something like:

var myArray = [];
for(var i in myObject) {
    myArray.push(myObject[i]);
}

Lastly, although not necessary in plain JavaScript, the JSON spec requires double quoting the key of the members. So the navite parser won't work without it. If I were you I would add it, but if it is not possible use the var myObject = eval( "(" + myString + ")" ); approach.

Steven Sudit
  • 19,391
  • 1
  • 51
  • 53
alcuadrado
  • 8,340
  • 3
  • 24
  • 25
  • What does var myObject = eval( "(" + myString + ")" ); mean? Thanks a lot. – MEM Aug 31 '10 at 15:33
  • 1
    eval() parses a string as JavaScript source, and as all valid JSON is also valid JavaScript (and it comes from JavaScript Object Notation), you can use eval() to transform it to it's JavaScript representation. It's a common practice to add parents at the beginning and end of the string for security reasons, although using eval() stills pretty insecure. So, var myObject = eval( "(" + myString + ")" ); is just parsing the myString JSON and getting it's value in myObject variable (probably an object or array) – alcuadrado Aug 31 '10 at 16:05
  • Note that json2 still uses eval, but performs some checks to mitigate potential vulnerabilities – Russ Cam Aug 31 '10 at 20:41
10

Since your string is malformed JSON, a JSON parser can't parse it properly and even eval() will throw an error. It's also not an Array but a HashMap or simply an Object literal (malformed). If the Object literal will only contain number and string values (and no child objects/arrays) you can use the following code.

function malformedJSON2Array (tar) {
    var arr = [];
    tar = tar.replace(/^\{|\}$/g,'').split(',');
    for(var i=0,cur,pair;cur=tar[i];i++){
        arr[i] = {};
        pair = cur.split(':');
        arr[i][pair[0]] = /^\d*$/.test(pair[1]) ? +pair[1] : pair[1];
    }
    return arr;
}

malformedJSON2Array("{a:12, b:c, foo:bar}");
// result -> [{a:12},{b:'c'},{foo:'bar'}]

That code will turn your string into an Array of Objects (plural).

If however you actually wanted a HashMap (Associative Array) and NOT an array, use the following code:

function malformedJSON2Object(tar) {
    var obj = {};
    tar = tar.replace(/^\{|\}$/g,'').split(',');
    for(var i=0,cur,pair;cur=tar[i];i++){
        pair = cur.split(':');
        obj[pair[0]] = /^\d*$/.test(pair[1]) ? +pair[1] : pair[1];
    }
    return obj;
}

malformedJSON2Object("{a:12, b:c, foo:bar}");
// result -> {a:12,b:'c',foo:'bar'}

The above code will become a lot more complex when you start nesting objects and arrays. Basically you'd have to rewrite JSON.js and JSON2.js to support malformed JSON.

Also consider the following option, which is still bad I admit, but marginally better then sticking JSON inside an HTML tag's attribute.

<div id="DATA001">bla</div>
<!-- namespacing your data is even better! -->
<script>var DATA001 = {a:12,b:"c",foo:"bar"};</script>

I am assuming you omit quote marks in the string because you had put it inside an HTML tag's attribute and didn't want to escape quotes.

BGerrissen
  • 21,250
  • 3
  • 39
  • 40
8

The simplest, but unsafe way to do it is:

eval('(' + myJSONtext + ')')

But since this will interpret any javascript code, it has security holes. To protect against this use a json parser. If you're using a framework (jquery, mootools, etc.) there's a framework-specific call. Most of them are based on Douglas Crawford's parser available at http://www.json.org/js.html.

Rob
  • 5,525
  • 1
  • 24
  • 26
  • Afaik, There are holes only if the eval is processing something entered by the user. I assume the user will not be involved in this question. – johny why Dec 02 '22 at 06:50
2

You can use "for in"

var myObject = {a:'12', b:'c', foo:'bar'};
var myArray = [];

for(key in myObject) {
    var value = myObject[key];
    myArray[key] = value;
}

myArray['a']; // returns 12

Notes: considering that myObject only have one level of key-value pairs.

Topera
  • 12,223
  • 15
  • 67
  • 104
  • If you really want to use a string, change first line to var myObject = eval('(' + "{a:'12', b:'c', foo:'bar'}" + ')');, using @Rob tip. – Topera Aug 13 '10 at 03:40
2

JSON.parse will do the trick. Once parsed, you can push them into the array.

var object = JSON.parse(param);
var array = [];
for(var i in object) {
   array.push(object[i]);
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Sarathi S
  • 571
  • 4
  • 11
1

If you're using jQuery, there's the $.parseJSON() function. It throws an exception if the string is malformed, and "Additionally if you pass in nothing, an empty string, null, or undefined, 'null' will be returned from parseJSON. Where the browser provides a native implementation of JSON.parse, jQuery uses it to parse the string"

jamiebarrow
  • 2,473
  • 3
  • 30
  • 51
0

Use safe evaluation. Unlike JSON.parse, this doesn't require the keys or values to be quoted. Quote values only if they contain embedded commas.

const myStr = "{a:1, b:2, c:3}";
const myObj = string_exp(myStr);
console.log("dot: " + myObj.c);

function string_exp(sCmd) {
    return Function(`'use strict'; return (${sCmd})`)();
}

https://dev.to/spukas/everything-wrong-with-javascript-eval-35on#:~:text=the%20variable%20exists.-,Alternatives,-The%20most%20simple

johny why
  • 2,047
  • 7
  • 27
  • 52