Help parsing JSON response


(Patrick Mjoen) #1

I am having an issue parsing the following url’s response and looking for some additional help:

http://scores.nbcsports.msnbc.com/ticker/data/gamesMSNBC.js.asp?jsonp=false&sport=NHL&period=20161017

as chrome and the debug for the response is a follows:

shsMSNBCTicker.loadGamesData({ “sport”: “NHL”, “period”: “20161017”, “games”: [ “” ,"" ,"" ,"" ]} );

But if I view the source code in Chrome it shows the following like it is not a proper JSON response:

shsMSNBCTicker.loadGamesData({
“sport”: “NHL”,
“period”: “20161017”,
“games”: [
"<ticker-entry gamecode=“2016101713” gametype=“Regular Season”><visiting-team display_name=“San Jose” alias=“SJ” nickname=“Sharks” id=“18” division=“WCP” conference=“WC” score=""><team-record wins=“2” losses=“0” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Sharks.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Sharks.png”><home-team display_name=“NY Rangers” alias=“NYR” nickname=“Rangers” id=“13” division=“ECM” conference=“EC” score=""><team-record wins=“1” losses=“1” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Rangers.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Rangers.png”><gamestate status=“Pre-Game” display_status1=“7:00 PM” display_status2="" href=“http://scores.nbcsports.msnbc.com/nhl/preview.asp?g=2016101713” tv=“CSCA/MSG” gametime=“7:00 PM” gamedate=“10/17” is-dst=“1” is-world-dst=“1”>"
,"<ticker-entry gamecode=“2016101716” gametype=“Regular Season”><visiting-team display_name=“Colorado” alias=“Col” nickname=“Avalanche” id=“17” division=“WCC” conference=“WC” score=""><team-record wins=“1” losses=“0” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Avalanche.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Avalanche.png”><home-team display_name=“Pittsburgh” alias=“Pit” nickname=“Penguins” id=“16” division=“ECM” conference=“EC” score=""><team-record wins=“2” losses=“0” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Penguins.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Penguins.png”><gamestate status=“Pre-Game” display_status1=“7:00 PM” display_status2="" href=“http://scores.nbcsports.msnbc.com/nhl/preview.asp?g=2016101716” tv=“Alti/ROOT” gametime=“7:00 PM” gamedate=“10/17” is-dst=“1” is-world-dst=“1”>"
,"<ticker-entry gamecode=“2016101705” gametype=“Regular Season”><visiting-team display_name=“Ottawa” alias=“Ott” nickname=“Senators” id=“14” division=“ECA” conference=“EC” score=""><team-record wins=“2” losses=“0” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Senators.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Senators.png”><home-team display_name=“Detroit” alias=“Det” nickname=“Red Wings” id=“5” division=“ECA” conference=“EC” score=""><team-record wins=“0” losses=“2” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/RedWings.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/RedWings.png”><gamestate status=“Pre-Game” display_status1=“7:30 PM” display_status2="" href=“http://scores.nbcsports.msnbc.com/nhl/preview.asp?g=2016101705” tv=“FSDT/RDS” gametime=“7:30 PM” gamedate=“10/17” is-dst=“1” is-world-dst=“1”>"
,"<ticker-entry gamecode=“2016101728” gametype=“Regular Season”><visiting-team display_name=“Boston” alias=“Bos” nickname=“Bruins” id=“1” division=“ECA” conference=“EC” score=""><team-record wins=“1” losses=“1” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Bruins.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Bruins.png”><home-team display_name=“Winnipeg” alias=“Wpg” nickname=“Jets” id=“28” division=“WCC” conference=“WC” score=""><team-record wins=“1” losses=“1” overtime-losses=“0”><team-logo link=“http://hosted.stats.com/nhl/logos/nhl_50x33/Jets.png” gz-image=“http://hosted.stats.com/GZ/images/Hockeylogos/Jets.png”><gamestate status=“Pre-Game” display_status1=“8:00 PM” display_status2="" href=“http://scores.nbcsports.msnbc.com/nhl/preview.asp?g=2016101728” tv=“NESN/TSN3” gametime=“8:00 PM” gamedate=“10/17” is-dst=“1” is-world-dst=“1”>"
]}
);

Im trying to parse the contents of the games array. Here is my source code for the smart app I am building:


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #2

shsMSNBCTicker.loadGamesData({ "sport": "NHL", "period": "20161017", "games": [ "" ,"" ,"" ,"" ]} );

Is 100% non-conforming to the JSON specifications (there are various websites that will syntax check).

However, I think if you just use JAVA String operations methods to strip this down to what is inside the (), then you can then easily parse the JSON inside, which is likely conforming.

http://www.json.org/


(Justin Wurth) #3

I think @tgauchat is correct, but I question your implementation of the use. A get statement only returns on something initiated from SmartThings. Unless there is something from the MSNBC ticker that you can send to SmartThings I am at a loss for how this would work. I don’t know that SmartThings API is set up to accept incoming triggers except for the native integrations they have setup.

@slagle could validate my statement above though.

I guess you could setup a refresh that would occur every so often but I don’t know how timely that would be to goal scoring. I think the other option is IFTTT, which then bridges the gap.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #4

SmartThings just added Asynchronous http calls.

Also, it isn’t unusual for a Service Manager SmartApp to poll for updates… For example Philips Hue, and Smart Weather Device, etc.


(Justin Wurth) #5

Async just means you are not waiting for a return command. It’s probably more of a lift to the system than it is to developers. Async does not mean you can request SmartThings do something from an outside website.

I think that is probably the solution to this problem is to have a webservice running on a rpi or on an aws instance and have it looking for the score and then issuing commands to SmartThings.


(Patrick Mjoen) #6

This is my first time writing a smart app (Only made a few DTH previously). I haven’t put the polling in until I got the service to reply with the data I needed. Once I can validate the data I was going to start adding the polling which will be different depending on when the game is going on and when it is not. I will look into using a Java string operation.


(Justin Wurth) #7

That will work if you are polling, but the frequency of polling is not that often so you may have some delay. I had done something similar with ESPN -> IFTTT -> SmartThings and some rgb lights I coded up and was never happy with how long it took for ESPN to post a score to their tracker. If this works well let me know.


(John S) #8

So the response is awesome - a string containing a javascript method call wrapping valid json containing a field (games) which is an array of strings that are valid XML

Or, as we would say “a hot mess”

You could strip the method call out, parse the json, then walk the games array of strings. For each item in there, either parse the string using an XML parser, or just use string operations to extract what you need.


(Patrick Mjoen) #9

Since I can only see this data using the new asynchttp_v1 (get method does not show the data in games just like this thread). Using this new asynchttp_v1 I can only see al the data if I use the raw string. Now looking for examples on parsing the string.


(Patrick Stuart [@pstuart]) #10

well, you will need to strip it down to a parsable xml format.

So groovy has string manipulation functions built in. take your response as a string (".toString()" ) and then use the replaceAll(“what to replace”,"") and strip it down from the left and right side (remove the JS function). Then it becomes json.

From there, get ST to parse the json using jsonbuilder. Get the games object (which is xml, kind of), as a string. Convert that from urlencoded to raw xml in string, then build it as xml, walk the tree to the elements you need.

This is not a trivial task, takes a lot of time but a good learning tool for parsing really poor data for sure.