21

I have a string similiar to document.cookie:

var str = 'foo=bar, baz=quux';

Converting it into an array is very easy:

str = str.split(', ');
for (var i = 0; i < str.length; i++) {
    str[i].split('=');
}

It produces something like this:

[['foo', 'bar'], ['baz', 'quux']]

Converting to an object (which would be more appropriate in this case) is harder.

str = JSON.parse('{' + str.replace('=', ':') + '}');

This produces an object like this, which is invalid:

{foo: bar, baz: quux}

I want an object like this:

{'foo': 'bar', 'baz': 'quux'}

Note: I've used single quotes in my examples, but when posting your code, if you're using JSON.parse(), keep in your mind that it requires double quotes instead of single.


Update

Thanks for everybody. Here's the function I'll use (for future reference):

function str_obj(str) {
    str = str.split(', ');
    var result = {};
    for (var i = 0; i < str.length; i++) {
        var cur = str[i].split('=');
        result[cur[0]] = cur[1];
    }
    return result;
}
3
  • Is this for a real project, or is this an attempt at a golf style question? Commented Feb 18, 2011 at 23:00
  • 4
    I wouldn't split on ', ' (note the space), but instead split on ',' (no space) and then trim the individual parts. This makes it unimportant whether 0, 1, 2, .. spaces or even tabs were used to 'beautify' the input string. Commented Nov 14, 2016 at 21:52
  • Sure would be nice if browsers would just implement a object version of cookies. Something like cookieObject would be nice. Commented Apr 14, 2021 at 19:50

13 Answers 13

36

The shortest way

 document.cookie.split('; ').reduce((prev, current) => {
    const [name, ...value] = current.split('=');
    prev[name] = value.join('=');
    return prev;
  }, {});
Sign up to request clarification or add additional context in comments.

2 Comments

Seems like the perfect situation to use reduce.
A problem with this solution is if the cookie contains "=". This could typically happen if the cookie is base64-encoded. To fix this: const [name, ...value] = current.split('='); prev[name] = value.join('=')
13

Why exactly do you need JSON.parse in here? Modifying your arrays example

let str = "foo=bar; baz=quux";

str = str.split('; ');
const result = {};
for (let i in str) {
    const cur = str[i].split('=');
    result[cur[0]] = cur[1];
}


console.log(result);

5 Comments

That produces ['foo=bar', 'baz=quux'], but I need an object.
@Nyuszika7H No, that produces an object and not array. You can't do result['foo'] on array.
@Nyuszika7H - nope, this does exactly what you demanded, as does my very similar example.
Sorry, I didn't see that the object is in the result variable. Thanks!
Note that this will fail if any of the "cookies" contain the cookie separator; this is probably not a problem, but could be if you use cookies for more complex data (such as in stackoverflow.com/questions/10119057).
5

note : The document.cookie (question headline) is semicolon separated and not comma separated (question) ...

An alternative using reduce :

var str = 'foo=bar; baz=quux';
var obj = str.split(/[;] */).reduce(function(result, pairStr) {
  var arr = pairStr.split('=');
  if (arr.length === 2) { result[arr[0]] = arr[1]; }
  return result;
}, {});

Comments

5

A way to parse cookies using native methods like URLSearchParams and Object.fromEntries, avoiding loops and temporary variables.

Parsing document.cookie:

Object.fromEntries(new URLSearchParams(document.cookie.replace(/; /g, "&")))

For the scope of the question (cookies are separated by , and stored in variable str)

Object.fromEntries(new URLSearchParams(str.replace(/, /g, "&")))

Comments

2

Given an array a containing your intermediate form:

[['foo', 'bar'], ['baz', 'quux']]

then simply:

var obj = {};
for (var i = 0; i < a.length; ++i) {
   var tmp = a[i];
   obj[tmp[0]] = tmp[1];
}

5 Comments

It isn't exactly correct, produces {'foo,bar': ['baz', 'quux']}.
corrected - I forgot to use tmp instead of a in the last line.
The suggested format is called entries (enumerable string-keyed property pairs). A shorter way to convert entries to an object is Object.fromEntries([['foo', 'bar'], ['baz', 'quux']])
@undefined that didn't exist in 2011.
@Alnitak makes sense, didn't see it's 2011 at the time. I'll still keep the comment here so people know this functionality exists now
2

parse cookies (IE9+):

document.cookie.split('; ').reduce((result, v) => {
  const k = v.split('=');
  result[k[0]] = k[1];
  return result;
}, {})

Comments

1

To convert it to an object, just do that from the beginning:

var obj = {};
str = str.split(', ');
for (var i = 0; i < str.length; i++) {
    var tmp = str[i].split('=');
    obj[tmp[0]] = tmp[1];
}

Then, if you want JSON out of it:

var jsonString = JSON.stringify(obj);

Comments

1

first thing that occurred to me, I'll leave it as the original version, but cookies should not be empty otherwise there will be a json parse error

JSON.parse(`{"${document.cookie.replace(/=/g,'":"').replace(/; /g,'","')}"}`)

fast and reliable version - cookie to object

let c=document.cookie.split('; '),i=c.length,o={};
while(i--){let a=c[i].split('=');o[a[0]]=a[1]}

and short function for get single cookie

getCookie=e=>(e=document.cookie.match(e+'=([^;]+)'),e&&e[1])

1 Comment

maybe for (let a of c) would be better. More readable and avoids creating a temporary i variable.
0

That's pretty crappy data, as long as its not using ,= this would work on that data

var text = 'foo=bar, baz=quux',
    pattern = new RegExp(/\b([^=,]+)=([^=,]+)\b/g),
    obj = {};

while (match = pattern.exec(text)) obj[match[1]] = match[2];

console.dir(obj);

Comments

0

I'm a fan of John Resig's "Search and don't replace" method for this sort of thing:

var str = 'foo=bar, baz=quux',
    arr = [],
    res = '{';

str.replace(/([^\s,=]+)=([^,]+)(?=,|$)/g, function ($0, key, value) { 
    arr.push('"' + key + '":"' + value + '"');
});

res += arr.join(",") + "}";

alert(res);

Working example: http://jsfiddle.net/cm6MT/.

Makes things a lot simpler without the need for JSON support. Of course, it's just as easy to use the same regular expression with exec() or match().


Whoops, I thought you wanted to convert to a JSON string, not an object. In that case, you only need to modify the code slightly:

var str = 'foo=bar, baz=quux',
    res = {};

str.replace(/([^\s,=]+)=([^,]+)(?=,|$)/g, function ($0, key, value) { 
    res[key] = value;
});
console.log(res.foo);
//-> "bar"

Working example 2: http://jsfiddle.net/cm6MT/1/

1 Comment

Please delete example 1 ! It is confusing because it returns a string ! See jsfiddle.net/pjja75hv
0

An alternate version of your updated solution that checks for the null/empty string and just returns an empty object and also allows for custom delimiters.

function stringToObject(str, delimiter) {
    var result = {};
    if (str && str.length > 0) {
        str = str.split(delimiter || ',');
        for (var i = 0; i < str.length; i++) {
            var cur = str[i].split('=');
            result[cur[0]] = cur[1];
        }
    }
    return result;
}

Comments

0

Most of the above solutions fail with the __gads cookie that Google sets because it uses a '=' character in the cookie value.

The solution is to use a regular expression instead of calling split('='):

document.cookie.split(';').reduce((prev, current) => {
  const [name, value] = current.split(/\s?(.*?)=(.*)/).splice(1, 2);
  prev[name] = value;
  return prev;
}, {});

2 Comments

Or just do const [name, ...value] = current.split('='); prev[name] = value.join('=')
You also need to remove the leading space, as in prev[name.slice(1)] = value.join('=')
0
function getCookie(){
   var o=document.cookie.split("; ");
   var r=[{}];
   for(var i=0;i<o.length;i++){
      r[o[i].split("=")[0]] = o[i].split("=")[1];
   }
   return r;
}

Just call getCookie() and it will return all cookies from the current website. If you have a cookie called 'mycookie' you can run getCookie()['mycookie']; and it will return the value of the cookie 'mycookie'. There is also a One-Line option:

function getCookie(){var o=document.cookie.split("; ");var r=[{}];for(var i=0;i<o.length;i++){r[o[i].split("=")[0]] = o[i].split("=")[1];}return r;}

This one can be used with the same methods as above.

Comments