4

I am doing a winJS.xhr like this :

var jsonResult;
WinJS.xhr(
{
    url: urlGoogle,
    responseType: 'json'
}
).done(function complete(response) {
    jsonResult = response.responseText;

    console.log(jsonResult);
}, 
//Error and Progress functions
);

The console log shows me this :

{lhs: "32 Japanese yen",rhs: "0.30613818 Euros",error: "",icc: true}

And I want to get the rhs info. So I tried doing

console.log(jsonResult.rhs); 

and

console.log(jsonResult['rhs']);

It only shows me "undefined". Then I realized that when I did a jsonResult[0], it shows me the first character (which is { ) and so on with the index bracket.

I tried to do a JSON.parse(jsonResult); but it creates an error

json parse unexpected character
Kalzem
  • 7,320
  • 6
  • 54
  • 79
  • you can simply parse it in javascript obj = JSON.parse(json); where json is the json object .... – AurA Nov 21 '12 at 08:02
  • 2
    @AurA: That didn't work, he says so in the last line of his question. – Cerbrus Nov 21 '12 at 08:08
  • json parse unexpected character is due to parsing an already parsed object...not a JSON string to be parsed some more help can be found in [this post](http://stackoverflow.com/questions/8524933/json-parse-unexpected-character-error) – AurA Nov 21 '12 at 08:12
  • actually unexpected character can have several causes. In this case I would guess it is due to keys such as `lhs` and `rhs` not being surrounded by quotes in the response. – sturrockad May 12 '14 at 14:58

6 Answers6

6

The string you are seeing isn't actually valid JSON as it's property names are not quoted. That is why JSON.parse is throwing an error.

Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
2

Just tried it on Chrome Dev Tools:

JSON.parse("{lhs: \"32 Japanese yen\",rhs: \"0.30613818 Euros\",error: \"\",icc: true}")
SyntaxError: Unexpected token l
JSON.parse('{lhs: "32 Japanese yen",rhs: "0.30613818 Euros",error: "",icc: true}')
SyntaxError: Unexpected token l
JSON.parse('{lhs: "32 Japanese yen",rhs: "0.30613818 Euros",error: "",icc: 1}')
SyntaxError: Unexpected token l
JSON.parse('{"lhs": "32 Japanese yen","rhs": "0.30613818 Euros","error": "","icc": true}')
Object
    error: ""
    icc: true
    lhs: "32 Japanese yen"
    rhs: "0.30613818 Euros"
    __proto__: Object

So it seems a "valid" JSON string should use double quote " to enclose every possible place.

Actually this also happens on PHP's json_decode.

I don't know about Win8JS development, so I'm not sure if you can use response.responeJSON or something like that, but directly parsing response.responseText seems likely to fail.

If you really need to use the responseText, consider @Cerbrus' dangerous eval method.

Passerby
  • 9,715
  • 2
  • 33
  • 50
  • - which is now modified to be *slightly less dangerous* (tm) – Cerbrus Nov 21 '12 at 08:31
  • @Cerbrus It's _tradition_ to say `eval` is dangerous :) Actually [MDN proposed `eval` to imitate JSON on old browsers](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON#Browser_compatibility). – Passerby Nov 21 '12 at 09:15
  • Oh, if MDN even uses `eval` (dangerous!), I guess we have no other choice. Abandon hope, all ye who `eval` here. – Cerbrus Nov 21 '12 at 09:18
  • I used the eval method as it seems to be the only one working. And I checked on winJS.xhr. There is no responseJSON, only responseText and responseXML (both of them are string). – Kalzem Nov 21 '12 at 23:07
1
var test = {lhs: "32 Japanese yen",rhs: "0.30613818 Euros",error: "",icc: true}
//test.lhs returns "32 Japanese yen"

I am not quite sure why this isn't working for you. Try logging the console.log(typeof jsonResult) to see if the jsonResult is a string or a object. (if it were a string, I'd say JSON.parse should've worked)
Then log jsonResult itself, and see if you can walk through it's properties. (The google chrome console works like a charm for this)

In case it is a string, this is a (Somewhat hacky, unsafe) way to do it:

var result = eval('({lhs: "32 Japanese yen",rhs: "0.30613818 Euros",error: "",icc: true})')
var result = eval('(' + jsonResult + ')')

(Thanks to @ThiefMaster♦ for some more proper(-ish) use of eval instead of my own abuse of it.)
You should then be able to access result
Generally, you don't want to use eval, but if all else fails...

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • I think OP has already hinted that his `jsonResult` is very likely to be a string, otherwise `jsonResult[0]` wouldn't return `{`. – Passerby Nov 21 '12 at 08:10
  • @Passerby: Added a option, if that's the case. – Cerbrus Nov 21 '12 at 08:16
  • -1 for using eval to parse json, another -1 if i could for putting the variable assignment inside the eval, too. Unfortunately using eval might be the way to go if the OP cannot get valid JSON from the remote system. Ah well, still -1 for the variable assignment inside the eval which is ugly/bad no matter what. However, assuming WinJS has access to the user's *system* using eval on possibly arbitrary JS is a very bad idea. – ThiefMaster Nov 21 '12 at 08:18
  • 1
    @ThiefMaster Well, thanks. If this is the only way he can get the data out of the result, it's still better than nothing right? The asker said he couldn't use `JSON.parse`, so if that's not a possibility, he should just not access the data at all, rather than use some ugly code? – Cerbrus Nov 21 '12 at 08:23
  • 1
    I'd say it's better than opening a security hole that'd possibly allow someone to gain access to the system. Anyway, `var result = ` should be outside the eval, i.e. `var result = eval('(' + jsonResult + ')')` – ThiefMaster Nov 21 '12 at 08:24
1

In your case ,Check the following

WinJS.xhr({ url: urlGoogle }).then(
           function completed(response) {
                var jsonString = JSON.parse(response.responseText);
                console.log(jsonString .rhs);
           },
           function error(error) { console.log(error) },
           function progress(progress) { }
);

OR

WinJS.xhr({ url: urlGoogle }).then(
           function completed(response) {
                var jsonString = JSON.parse(response.responseText);
                 console.log(jsonString .rhs); 
           },
           function error(error) { console.log(error) },
           function progress(progress) { }
);
Sai
  • 1,376
  • 2
  • 15
  • 25
0

First do:

jsonResult = JSON.parse(response.responseText);

and then you can use:

var rhs = jsonResult.rhs;
Blundering Philosopher
  • 6,245
  • 2
  • 43
  • 59
-1

I have blogged about this in the past. The code below calls into a web service that returns JSON.

It is explained here: http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/06/step-4-augmented-reality-windows-8-and-cloud-computing-how-to-implement-with-real-code-implementing-the-windows-8-client.aspx#

What is useful about this code is that you "try" to get the values. They may not exist.

See parsedResults.TryGetValue().

    private async System.Threading.Tasks.Task CallLocationWebService(string gps)
    {
        // Call into the emulator. This assumes you are running the
        // cloud project from the last post in the backgruond
        string _location = "http://127.0.0.1:81/api/values?location={0}";

        // You can use the line below once you deploy your cloud
        // application to the cloud (a MS data center)
        //string _location = "http://locationwebservice.cloudapp.net/api/values?location={0}";

        // Now make the aynchronous call. We need to pass the GPS
        // parameters here to the _location string mentioned above.
        using (HttpClient clientlocation = new HttpClient())
        using (var response = await clientlocation.GetAsync(string.Format(_location, gps)))
        {
            if (response.IsSuccessStatusCode)
            {
                string webresponse = await response.Content.ReadAsStringAsync();

                // Parse the string into a JSONObject
                var parsedResults = JsonObject.Parse(webresponse);

                IJsonValue val;

                // Extract data embedded in JSONObject.
                // Assign to controls in user interface
                if (parsedResults.TryGetValue("latitude", out val))
                    loc_info.latitude = val.GetString();
                if (parsedResults.TryGetValue("longitude", out val))
                    loc_info.longitude = val.GetString();
                if (parsedResults.TryGetValue("bus_and_neighborhood", out val))
                    loc_info.bus_and_neighborhood = val.GetString();
                if (parsedResults.TryGetValue("elevation", out val))
                    loc_info.elevation = val.GetString();
                if (parsedResults.TryGetValue("bus_and_neighborhood", out val))
                    loc_info.bus_and_neighborhood = val.GetString();
                if (parsedResults.TryGetValue("max_temp", out val))
                    loc_info.max_temp = val.GetString();
                if (parsedResults.TryGetValue("min_temp", out val))
                    loc_info.min_temp = val.GetString();

                this.bus_and_neighborhood.Text = loc_info.bus_and_neighborhood;
                this.elevation.Text = loc_info.elevation;
                this.latlong.Text = loc_info.latitude + "/" + loc_info.longitude;
                this.max_temp.Text = loc_info.max_temp;
                this.min_temp.Text = loc_info.min_temp;
            }
        }

    }
Bruno
  • 498
  • 1
  • 4
  • 9