46

I am attempting to store an array in the HTML data tag. For example:

<div data-locs="{'name':'London','url':'/lon/'},{'name':'Leeds','url':'/lds'}">

I am accessing that data using jQuery. I realise that this is stored as a string, and I've tried various methods to convert it to an array, but I've hit a wall. If you take a look at this jsFiddle page you'll see a full example of what I'm trying to do.

http://jsfiddle.net/B4vFQ/

Any ideas?

Thanks!

will
  • 4,557
  • 6
  • 32
  • 33

4 Answers4

91

If you use valid JSON ([ and ] for the array, double quotes instead of single), like this:

<div id="locations" data-locations='[{"name":"Bath","url":"/location/bath","img":"/thumb.jpg"},{"name":"Berkhamsted","url":"/location/berkhamsted","img":"/thumb.jpg"}]'>

Then what you have (using .data()) to get the array will work:

$('#locations').data('locations');

You can test it here.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • 2
    +1 I didn't realize jQuery would parse JSON automatically for you. Do you happen to know off hand how it detects it? Or does it just do a `try/catch`. EDIT: Nevermind, looks like it's a `try/catch`. – user113716 Nov 26 '10 at 17:52
  • @patrick - jQuery 1.4.3+ with `.data()` does the work here, it detects the type...also converts numbers, etc as well – Nick Craver Nov 26 '10 at 17:53
  • 2
    @cambraca - If the browser supports it yes, but something has to call `JSON.parse()` (and jQuery does this if it's JSON in there), you can see it happening here: https://github.com/jquery/jquery/blob/master/src/data.js#L203-218 – Nick Craver Nov 26 '10 at 17:56
  • 1
    @Nick - Yes, I was just wondering how `.data()` knows it is `JSON`. Answer seems to be that it doesn't do any particular detection. Just takes a stab at it. EDIT: I should clarify that in my original comment I didn't mean jQuery itself was parsing the `JSON`. It was sloppy wording. – user113716 Nov 26 '10 at 17:56
  • @patrick - Look at the code in my last comment, it's running this regex to determine it's JSON: https://github.com/jquery/jquery/blob/master/src/data.js#L4 – Nick Craver Nov 26 '10 at 18:00
  • @Nick - Ah, I overlooked the `rbrace` part of the conditional operator. Looks like a simple test. OPs original code would pass, hence the `try/catch`. Thanks. :o) EDIT: It would seem that they could reduce some needless calls by adding an opening `"` to the test like: `{"`. – user113716 Nov 26 '10 at 18:03
  • 3
    One slight gotcha: You need single quotes to enclose the data-foo html attribute and double quotes for valid JSON. With valid JSON (I simply generate it with json_encode() in php) then you escape any double quotes in the data itself to \". BUT, if you have any single quotes in the data itself (my data included names which can, for eample, be O'Connor) then the whole thing breaks down since only the part of the json up to the single quote is counted as the attribute value. Escaping with \' does NOT work, but it seems that html entities do. E.g. str_replace("'", "’", json_encode($foo)) – Adam Feb 08 '13 at 15:58
6

Try adding [ and ] to beginning and end (this makes it valid JSON). After doing so, you can use JSON.parse() to convert it to a native JavaScript object.

jwueller
  • 30,582
  • 4
  • 66
  • 70
  • jQuery already does this if it's valid JSON (double quotes)...just adding `[]` would blow up, since native `JSON.parse` needs valid JSON to work, and single quotes aren't it :) – Nick Craver Nov 26 '10 at 17:48
  • @Nick Craver: You're right! I did not know that jQuery does this automatically. Quite awesome. – jwueller Nov 26 '10 at 17:55
0

If for whatever reason you insist on using double quotes, you will need to html encode the quotes in your data attribute.

<div data-dwarfs="[&quot;Doc&quot;, &quot;Sneezy&quot;, &quot;Happy&quot;]"></div>

Of course if you have access to PHP or some other pre-processor, you could use something like this:

<?php
    $dwarfs = ['Doc', 'Sneezy', 'Happy'];
?>
    <div data-dwarfs="<?php echo htmlspecialchars(json_encode($dwarfs), ENT_QUOTES, 'UTF-8') ?>"></div>
<?php
Jules Colle
  • 11,227
  • 8
  • 60
  • 67
  • Thanks for the down vote, but I promise you that I tested this thoroughly, so I'm confident that my answer is correct. – Jules Colle Jan 24 '21 at 12:58
-3

Try this:

var testOne = eval("new Array(" + $('#locations').data('locations') + ")");

Look at it in jsfiddle.

cambraca
  • 27,014
  • 16
  • 68
  • 99
  • 2
    This isn't a good or safe way to extract data, avoid `eval()` whenever possible. Using actual JSON here is both more correct and faster, why not use correct markup? :) – Nick Craver Nov 26 '10 at 17:47
  • @Nick: Yeah I agree adding [] to the attribute is a better option – cambraca Nov 26 '10 at 17:50
  • that actually won't solve the issue, quotes are incorrect as well, but definitely the better approach, to fix the problem not the symptoms – Nick Craver Nov 26 '10 at 17:51