Link to home
Start Free TrialLog in
Avatar of bamapie
bamapie

asked on

json string to object

I'm working with a tool that uses JSON data.  Now I'm trying to feed it my own JSON data that I build as a string then try to convert to a JSON object.

I'm using jQuery, so I've tried the jQuery string-to-JSON-object method, and I've tried just JSON.parse(str).  Everything returns NULL.

Here's their example data.  Of course, in their example, they're not returning a string from the server and trying to cast it into a JSON object.  It's already neatly ready to work perfectly, as a hard-coded JSON structure.

Here's the JS of their example:

      var timeline;
      var data;
      
      // Called when the Visualization API is loaded.
      function drawVisualization() {
        // Create a JSON data table
        data = [
          {
            'start': new Date(2010,7,23),
            'content': 'Conversation<br><img src="img/comments-icon.png" style="width:32px; height:32px;">'
          },
          {
            'start': new Date(2010,7,23,23,0,0),
            'content': 'Mail from boss<br><img src="img/mail-icon.png" style="width:32px; height:32px;">'
          }        
        ];

        // Draw our timeline with the created data and options 
        timeline.draw(data, options);

Open in new window


This works great for them.  It's nice and handy because they're using a ready-made string.

My attempts just return null:

   var oData = jQuery.parseJSON(sData);

   or

   var oData = JSON.parse(sData);

What's the secret?  How can I take my JSON-like string and make it into a real JSON object that I can feed this damn jQuery timeline widget?

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Lee Wadwell
Lee Wadwell
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of bamapie
bamapie

ASKER

Here's a very pared-down string that I've been unsuccessfully trying to convert to a JSON object that this tool will accept.  This is the current value I'm trying unsuccessfully:

"[{'start': new Date(2010,7,23),'content': 'Conversation'}]"
Well ... as it turns out - your JSON-like string is not JSON-like enough.  Check out this site to validate strings as JSON http://jsonlint.com/
Two problems I found were:
a) use single quotes - not valid JSON, only double quotes.
b) use of "new Date()" as an open function and not as a quoted string - also not valid JSON.

An extremely UNSAFE approach is to use eval() ... but it is exactly that, unsafe it runs code embedded in the string and can lead to unwanted results.

Another is to fix the string and use a 'reviver' approach is you need the dates to be resolved in the JSON.
Look at this example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Q_27833573</title>

    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
    <style type="text/css">
    * {
        font-family: Arial;
    }
    </style>
    <script type="text/javascript">
    $(document).ready(function(){
        var jsonString = "[{'start': new Date(2010,7,23),'content': 'Conversation'},{'start': new Date(2011,10,24),'content': 'Another Conversation'}]";
        console.log("String>> ",jsonString);
        
        // Method 1 - using eval() ... UNSAFE
        var jsonObj = eval(jsonString);
        
        // some logging and output
        console.log("String as JSON>> ",jsonObj);
        $('#eg01a').html(jsonString);
        for ( var i in jsonObj ) {
            var msg = "Start Date: " + jsonObj[i].start + " Content: " + jsonObj[i].content;
            $('#eg01b').append($("<p/>").text(msg));
        }
        
        // Reworked JSON string to use double quotes " and single quotes are NOT valid in JSON
        var jsonString2 = '[{"start": "new Date(2010,7,23)","content": "Conversation"},{"start": "new Date(2011,10,24)","content": "Another Conversation"}]';
        
        // Method 2 - using parse() with reviver
        var jsonObj2 = JSON.parse(jsonString2, function (key, value) {
            if ( typeof value === 'string' ) {
                var a =/^new Date\((\d{4}),(\d{1,2}),(\d{1,2})\)$/.exec(value);
                if (a) {
                    value = new Date(a[1],a[2],a[3]);
                }
            }
            return value;
        });
        // some logging and output
        console.log("String as JSON>> ",jsonObj2);
        $('#eg02a').html(jsonString2);
        for ( var i in jsonObj2 ) {
            var msg = "Start Date: " + jsonObj2[i].start + " Content: " + jsonObj2[i].content;
            $('#eg02b').append($("<p/>").text(msg));
        }
        
    });
    </script>
</head>
<body>

    <h3>Example 01a</h3>
    <div id="eg01a"></div>
    <h3>Example 01b</h3>
    <div id="eg01b"></div>
    <h3>Example 02a</h3>
    <div id="eg02a"></div>
    <h3>Example 02b</h3>
    <div id="eg02b"></div>

</body>
</html>

Open in new window

Avatar of bamapie

ASKER

Now remember, my original post was stripped out of a WORKING example.  So I'm only patterning my JSON after the working example.
In the working example the 'new Date()' is resolved at time of creation ... the function call is not stored in the JSON ... the date returned is however.
As for the use of single quotes, JavaScript is obviously more forgiving, hence why it works in an eval().  But the parse() function is strict.

Add this example in and try ... this uses the the stringify() function to turn the JSON into a string.
        var data = [ 
          {
            'start': new Date(2010,7,23),
            'content': 'Conversation'
          },
          {
            'start': new Date(2010,7,23,23,0,0),
            'content': 'Mail from boss'
          }        
        ];
        var strFromJSON = JSON.stringify(data);
        console.log("JSON as String>> ",strFromJSON);
        $('#eg03').html(strFromJSON);

Open in new window


Why are you creating it as a string anyway?
Avatar of bamapie

ASKER

My data is dynamic.  Users will add and remove series of data to their timeline.  No way I can "burn it in" to a JS or HTML file.

Their example is nice and tidy in that it's completely static data.  NOT representative of the real world, however.

It will be built on and then returned from an async call to the server.  I just figured I could build a string, formatted in the style of their example, and find a way to present it to their display() function in a way that it accepted it.
What do you mean "burn it in"?  JSON is modifiable.
Avatar of bamapie

ASKER

Look at this example.  View source on it:

http://links.sourceforge.net/timeline/js/examples/example17_json_data.html

Their data is "burned into" the JS on this page.  It's static.  

I can't do that.  Mine will need to be provided dynamically from the server in a way that THIS TOOL is okay with it.

This is what I need.  To make this tool as happy with my dynamic data as it happens to be with this example that uses static data burned into their HTML file.

The approach I was going to take was to try to return a string from the server via an ajax function, and "cast" that string somehow into whatever JSON format that this tool is happy with.
Why not use JSON to and from the server using AJAX?  What will the server side be coded in?

But if you want to use strings ... I have explained the constraints you will need to follow for your example string.
Avatar of bamapie

ASKER

ASP.NET on the server side.

I've shown you the single way I've seen this tool work.  

So now, that's what I am trying to replicate by posting this question.
Avatar of bamapie

ASKER

I'm going to close this question so I can get you some points.  Then re-post it.  

Please allow me to troll around for some hard-and-fast ideas on that new question.  Your general ideas are dead-on, I'm sure, but I need less 30K-foot view and more how-do-I-do-this.