tags:

views:

48

answers:

2

I am working on a GWT app that is receiving a JSON string, and I'm having a hard time getting down to the values of each object. I'm trying to transfer the incoming JSON string into an array of objects.

Here is the JSON (From Firebug response tab), The "d" is a .NET thing (Web Service Being Consumed is C#.

{
    "d": [
        {
            "__type": "Event",
            "ID": 30,
            "Bin": 1,
            "Date": "\/Date(1281544749000)\/",
            "Desc": "Blue with white stripes.",
            "Category": "1"
        },
        {
            "__type": "Event",
            "ID": 16,
            "Bin": 3,
            "Date": "\/Date(1281636239000)\/",
            "Desc": "Yellow with pink stripes",
            "Category": "1"
        }

    ]
}

I'm trying to parse the JSON into objects, and then insert them into an array. I'm able to use Window.alert and get the entire "d" object to echo. However, when I try to access the elements of the array, GWT debugger just crashes.

//My GWT array to receive JSON Array
ArrayList<Item> itemInfo = new ArrayList<Item>();

//Getting response JSON into something I can work with.(THIS FAILS) 
JSONArray jsonValue = JSONParser.parse(incomingJsonRespone);

//Just trying to verify I'm getting values 
for (int i=0; i<jsonValue.size(); i++) {
    JSONValue jsonItem =  = JsonValue.get(i).getString();
    Window.alert(jsonItem);
    itemInfo.add(jsonItem);

}

I think I have narrowed down the problem to where the JSONArray instance is being created. Is there something blatantly wrong with how I'm trying to do this, because I'm not getting much help in the way of error messages?

+1  A: 

It looks like you don't have an array, but a single root object, whose property called 'd' is an array. I'm not familiar with that specific API, but maybe you can try retrieving a JSONObject or similar instead of an array?

RMorrisey
@RMorrisey -Thanks, I think I see what you are saying. Do you mean parse it into an JSONObject, then into a JSONArray? Or just access the string values directly from the JSONObject?
cinqoTimo
Do you have a link to an API doc for the JSONParser library you are using?
RMorrisey
I don't know what the proper calls are, but I think it should be something like: JSONParser.parse(incomingJsonResponse).getObject("d").getArray()or JSONParser.parse(incomingJsonResponse).getArray("d")
RMorrisey
+3  A: 

In response to RMorrisey's comment:
Actually, it's more convoluted :/ It would look something like this (code untested, but you should get the general idea):

JSONValue jsonValue;
JSONArray jsonArray;
JSONObject jsonObject;
JSONString jsonString;
jsonValue = JSONParser.parseStrict(incomingJsonRespone);
// parseStrict is available in GWT >=2.1
// But without it, GWT is just internally calling eval()
// which is strongly discouraged for untrusted sources

if ((jsonObject = jsonValue.isObject()) == null) {
    Window.alert("Error parsing the JSON");
    // Possibilites: error during download,
    // someone trying to break the application, etc.
}

jsonValue = jsonObject.get("d"); // Actually, this needs
                                 // a null check too
if ((jsonArray = jsonValue.isArray()) == null) {
    Window.alert("Error parsing the JSON");
}

jsonValue = jsonArray.get(0);
if ((jsonObject = jsonValue.isObject()) == null) {
    Window.alert("Error parsing the JSON");
}

jsonValue = jsonObject.get("Desc");
if ((jsonString = jsonValue.isString()) == null) {
    Window.alert("Error parsing the JSON");
}

Window.alert(jsonString.stringValue()); // Finally!

As you can see, when using JSONParser you have to/should be very cautious - that's the whole point, right? To parse an unsafe JSON (otherwise, like I suggested in the comments, you should go with JavaScript Overlay Types). You get a JSONValue, check if it's really what you think it should be, say, a JSONObject, you get that JSONObject, check if it has the "xyz" key, you get a JSONValue, rinse and repeat. Not the most interesting work, but at least its safer than just calling eval() on the whole JSON :)
Attention: as Jason pointed out, prior to GWT 2.1, JSONParser used eval() internally (it only had a parse() method - GWT 2.0 javadocs vs GWT 2.1). In GWT 2.1, parse() became deprecated and two more methods were introduced - parseLenient() (uses eval() internally) and parseStrict() (the safe approach). If you really have to use JSONParser, then I'd suggest upgrading to GWT 2.1 M2, because otherwise you might as well use JSOs. As an alternative to JSONParser for untrusted sources, you could try integrating json2.js as a JSON parser via JSNI.

PS: cinqoTimo, JSONArray jsonValue = JSONParser.parse(incomingJsonRespone); obviously doesn't work because JSONParser.parse has a return type of JSONValue, not JSONArray - didn't your IDE (Eclipse + Google Plugin?) warn you? Or at least the compiler.

Igor Klimer
Make sure to use `JSONParser`'s `parseStrict()` method for untrusted/arbitrary JSON: "CAUTION! For efficiency, this method is implemented using the JavaScript `eval()` function, which can execute arbitrary script. DO NOT pass an untrusted string into this method." (from http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/json/client/JSONParser.java )
Jason Hall
Hmm, I was under the impression that `JSONParser` used a safer approach... I was going to suggest `parseStrict()`, but then I noticed that it's been introduced in GWT 2.1, so OP might not have it available yet. But in light of Jason's comment, I guess it's best to upgrade to GWT 2.1 M2 and use `parseStrict()` - otherwise, `JSONParser` has little to none benefits over JSO.
Igor Klimer
@Igor Klimer - The code isn't exactly right, but the idea was correct. Thanks
cinqoTimo