开发者

Parsing malformed JSON with Javascript

I want to parse this content using Javascript. The data looks like this:

{"ss":[["Thu","7:00","Final",,"BAL","19","ATL","20",,,"56808",,"PRE4","2015"],["Thu","7:00","Final",,"NO","10","GB","38",,,"56809",,"PRE4","2015"]]}

Every single tutorial online teaches you how to parse JSON using Twitter, but I am not quite sure how parsing with JSON works.

I would like to set this up on a website to view the NFL team scores for a fun project and a good learning experience about parsing JSON, as I could care less about Twitter stuff.

Is this possible?开发者_运维百科 Any good tutorials to start with? Even some starting code?


Generally speaking, you can use JSON.parse to do this. However, that snippet that you have does not appear to be strictly valid JSON (as seen here: http://jsfiddle.net/yK3Gf/ and also by validating the source JSON here: http://jsonlint.com/).

So you will either need to parse it by hand, or get nfl.com to fix up their JSON.

As an alternative, their JSON does parse successfully when using eval(), so you could parse it with something like:

var parsedData = eval('(' + jsonData + ')');

...as shown here: http://jsfiddle.net/yK3Gf/1/

Though be aware that parsing JSON in this way is generally frowned upon (particularly when the data being parsed is being delivered by a third-party source), as it leaves you open to XSS attacks should the data happen to include any executable code inside of it.


I am in a similar position - non javascript expert working on a fun project to familiarize myself with javascript, ajax, and json.

I took three different steps to handle the problem. I welcome any feedback on improving the solution.

The first step is to query the nfl site to pull down the scores. Because the source of the json, the nfl site, is different from your site, you will have to work around the javascript security constraints against cross domain querying. I found this stackoverflow link to be a good reference. I used JSONP for the workaround. I used http://whateverorigin.org/ as the indirection site.

$.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent('http://www.nfl.com/liveupdate/scorestrip/scorestrip.json') + '&callback=?', handleQueryForScoresResult);

As others have pointed out, the nfl site returns invalid json data. The following sample line illustrates the problem:

["Sun","4:25","Final",,"TEN","7","MIN","30",,,"55571",,"REG5","2012"],

Notice the empty array element values (the repeated commas with no data in between). So in my json callback function, I corrected the data by adding empty strings (two double quotes) to repeated commas before calling jquery to parse the json data:

function handleQueryForScoresResult(data) {
    var jsonStr = data.contents;
    jsonStr = jsonStr.replace(/,,/g, ',"",');
    jsonStr = jsonStr.replace(/,,/g, ',"",');

    var scoresData = jQuery.parseJSON(jsonStr).ss;
    .
    .
    .
}

Lastly, I created GameScores object to encapsulate the json data.

function GameScore(scoreData) {
    this.scoreData = scoreData;
    scoreData[2] = scoreData[2].toLowerCase();
    scoreData[5] = parseInt(scoreData[5]);
    scoreData[7] = parseInt(scoreData[7]);
} 

function GameScore_getAwayTeam() { return this.scoreData[4]; }
function GameScore_getHomeTeam() { return this.scoreData[6]; } 
function GameScore_isFinal() { return this.scoreData[2]=="final"; }  
function GameScore_getHomeTeamScore() { return this.scoreData[7]; }
function GameScore_getAwayTeamScore() { return this.scoreData[5]; }
function GameScore_doesHomeTeamLead() { return this.scoreData[7]> this.scoreData[5]; }
function GameScore_doesAwayTeamLead() { return this.scoreData[5]> this.scoreData[7]; }
function GameScore_getWeekId() { return this.scoreData[12]; }

GameScore.prototype.getHomeTeam = GameScore_getHomeTeam;
GameScore.prototype.getAwayTeam = GameScore_getAwayTeam;
GameScore.prototype.isFinal = GameScore_isFinal;
GameScore.prototype.getHomeTeamScore = GameScore_getHomeTeamScore;
GameScore.prototype.getAwayTeamScore = GameScore_getAwayTeamScore;
GameScore.prototype.doesHomeTeamLead = GameScore_doesHomeTeamLead;
GameScore.prototype.doesAwayTeamLead = GameScore_doesAwayTeamLead;
GameScore.prototype.getWeekId = GameScore_getWeekId;

I only added a few accessors as I did not need most of the data. Your needs may vary.


We are using mootools for stuff like that, but you can do it it plain JavaScript as well: http://www.json.org/js.html.


Let's assume you already have a valid JSON String (jsonString) to parse. (If you don't know how to retrieve a String to parse using XMLHttpRequest from the given url you will have to look into that first.)


With plain JavaScript you will have to add Douglas Crockford's JSON library (or something similar) in order to provide a parsing Function if there is no native implementation:

var json = json_parse(jsonString) ;
  • link

With a JavaScript library like jQuery this would be

var json = $.parseJSON(jsonString) ;

Now, traversing the resultant JSON Object is a whole other issue, because you will have to know its structure before you can retrieve specific data. In this particular case -- if it was indeed well formed -- you would have to do the following:

var data = json.ss ;

     for(var i = 0 ; i < data.length ; i++) {

          var entry = data[i] ;

          var day = entry[0] ; //!! the Arrays seem to have a format where the first entry always contains the data and so forth...
          /* ... */

          // then do something with the data bits

     }


Your main problem is that fact that the JSON your pulling in is malformed or not valid according to RFC 4627.

What you can do is grab the copy the JSON data and format it using this tool http://www.freeformatter.com/json-formatter.html

After you have the formatted version then you can use the jQuery ajax call

$.ajax({
    url: "your-formatted.json",
    dataType: 'json',

    success: function (data) {

        for (var i = 0; i < data.ss.length; i++) {
            document.write("Day: " + data.ss[i][0]);
            document.write("<br/>");
            document.write("Time: " + data.ss[i][1]);
            document.write("<br/><br/>");
        }
    }
});

You shouldn't actually use document.write in your application. This is only for example purpose of displaying the data.


For this specific issue (the empty indexes within the arrays from the JSON response) I did a regex replacement with a lookahead assertion. Considering that request contains the XMLHttpRequest:

request.responseText.replace(/,(?=,)/gm, ",\"\"")

This will turn ,, into ,"", and will also work in case there are more commas in sequence, so ,,, becomes ,"","",. You can use JSON.parse() afterwards.


This malformed JSON can be parsed by the dirty-json NPM package (I am the author).

You can test a demo of the parser here: https://rmarcus.info/dirty-json

The parser interprets the JSON in your original question as equivalent to the following valid JSON:

{
    "ss": [
        [
            "Thu",
            "7:00",
            "Final",
            "BAL",
            "19",
            "ATL",
            "20",
            "56808",
            "PRE4",
            "2015"
        ],
        [
            "Thu",
            "7:00",
            "Final",
            "NO",
            "10",
            "GB",
            "38",
            "56809",
            "PRE4",
            "2015"
        ]
    ]
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜