1

I use JSON in hidden element in HTML to avoid multiple unnecessary AJAX requests. JSON is generated properly but I can't handle it using JQuery so I can work with it.

The problem is that elem.data("json") returns an object instead of string so parseJSON says that there is unexpected o at the start of the string.

$(document).ready(function () {
    console.log($('#locations-json').data('json'));   
    console.log(JSON.parse($('#locations-json').data('json'))); # tried parseJSON
    $('.class-destination-from').change(function () {
        $.when(get_destination_from_state(),function(res){
            //if (res=='city'){
            //
            //}elif(res=='airport'){
            //    pass
            //}elif(res=='empty'){
            //    pass
            //}
        });
    })
});

CONSOLE

Object {cities: "[1, 2, 3, 4]", airports: "[5, 6]"} VM1345:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1

This is the part of HTML:

<div id="locations-json" data-json="{&quot;cities&quot;: &quot;[1, 2, 3, 4]&quot;, &quot;airports&quot;: &quot;[5, 6]&quot;}" style="display: none"></div>

Do you know how to convert it properly?

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
Milano
  • 18,048
  • 37
  • 153
  • 353
  • 1
    JSON objects must have quoted keys: `{ "cities": "[1, 2, 3, 4]", "airports": "[5, 6]"}` – Frxstrem Sep 30 '16 at 08:56
  • Possible duplicate of [Serialize form data to JSON](http://stackoverflow.com/questions/11338774/serialize-form-data-to-json) – SAM Sep 30 '16 at 08:56
  • @T.J.Crowder I've added the element at the bottom of the question. – Milano Sep 30 '16 at 09:00

1 Answers1

4

The problem, as it so often is, is that data isn't what most people think it is. data is not an accessor for data-* properties, it's both more and less than that. It manages jQuery's internal data cache for the element. It initializes that cache from data-* attributes, but it duplicates the data in the cache, processes the data, and never writes back to the attributes.

It's that "processing the data" that's hitting you in this case: data automatically detects that what you're reading is JSON and parses it for you. So you'll get back an object, and don't need to parse it.

So using data:

var locations = $("#locations-json").data("json");
console.log(locations);
console.log("There are " + locations.cities.length + " cities");
<div id="locations-json" data-json="{&quot;cities&quot;: &quot;[1, 2, 3, 4]&quot;, &quot;airports&quot;: &quot;[5, 6]&quot;}" style="display: none"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

As you noted in a comment, that says there are 12 cities. That's because the JSON gives cities (and airports) a string value:

{"cities": "[1, 2, 3, 4]", "airports": "[5, 6]"}

You probably meant the JSON to be:

{"cities": [1, 2, 3, 4], "airports": [5, 6]}

Example:

var locations = $("#locations-json").data("json");
console.log(locations);
console.log("There are " + locations.cities.length + " cities");
<div id="locations-json" data-json="{&quot;cities&quot;: [1, 2, 3, 4], &quot;airports&quot;: [5, 6]}" style="display: none"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

But unless you need the various features of data, just use attr and parse yourself:

var locations = JSON.parse($("#locations-json").attr("data-json"));
console.log(locations);
console.log("There are " + locations.cities.length + " cities");
<div id="locations-json" data-json="{&quot;cities&quot;: [1, 2, 3, 4], &quot;airports&quot;: [5, 6]}" style="display: none"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Note:

As of this edit, your question had a valid div that looked like this:

<div id="locations-json" data-json="{&quot;cities&quot;: &quot;[1, 2, 3, 4]&quot;, &quot;airports&quot;: &quot;[5, 6]&quot;}" style="display: none"></div>

But then you edited it again to look like this, which is invalid:

<div id="locations-json" data-json="{"cities": "[1, 2, 3, 4]", "airports": "[5, 6]"}" style="display: none"></div>

The version with &quot; is correct, be sure to use that.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I'm not sure if it parses the JSON correctly but I'm new in this area so It could be correct. When I do: $('#locations-json').data('json').cities it returns [1, 2, 3, 4] which is correct. But when I try to get the first city - so 1 - it returns "[" like it thinks that the array is a string. – Milano Sep 30 '16 at 09:05
  • @MilanoSlesarik: See my comment on the question, you need to make sure your element's `json` attribute is correctly output. I've also added a note about that to the end of the answer above. – T.J. Crowder Sep 30 '16 at 09:08
  • Maybe I don't get something but your code returns that there are 12 cities so it consideres the values are strings, not array/lists. – Milano Sep 30 '16 at 09:13
  • @MilanoSlesarik: Well-spotted. They **are** strings in the JSON. If you don't want them to be strings, remove the quotes around them. – T.J. Crowder Sep 30 '16 at 09:15