Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way for parsing JSON objects containing arrays in Java Servlets (with Gson for example)

I know this is a topic much talked about, but I still wasn't able to find a correct and clear answer to my specific problem.

I've got a JSON that looks like this:

var myData = {  "gameID" : gameID,
                "nrOfPlayers" : 2,
                "playerUIDs" : [123, 124]
            };

The Question I have is exactly what is the correct way (or best way, style wise) to parse this in a Java servlet (using GSON for example)? First I send this JSON to the server using jQuery ajax method like this:

jQuery.ajax({
        url : path,
        data : myData,
        success : successFunction,
        error : function(data) {
            console.log("Error: ", data);
        }  ,
        type : "post",
        timeout : 30000
    });

Now in the servlet I've learned that I should have been able to parse that JSON like this:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Gson gson = new Gson();

        String gameID = gson.fromJson(request.getParameter("gameID"), String.class);
        String nrOfPlayers = gson.fromJson(request.getParameter("nrOfPlayers"), String.class);
        String[] playerUIDs = gson.fromJson(request.getParameter("playerUIDs"), String[].class);

        log.info(gameID);
        log.info(nrOfPlayers);
        log.info(playerUIDs[0] +" "+ playerUIDs[1]);
}

But the playerUIDs variable IS NULL and of course playerUIDs[0] throws an exception!

Digging deeper I found that when looping over the request parameter names, it contained a parameter named "playerUIDs[]" with the value of only 123 (the first int in the array). This was strange cause I didn't seem to be able to access the next values at all.

Then I read that JSON objects should be stringifyed before POST-ing so I added JSON.stringify(myData), but now the request parameter names only contained ONE name which was the JSON object itself in a stringified state:

INFO: Parameter name = {"gameID":"b6a51aabb8364b04bce676eafde1bc87","nrOfPlayers":2,"playerUIDs":[123,124]}

The only way I seemed to get this to work was by creating a inner class:

class GameStart {
    protected String gameID;
    protected int nrOfPlayers;
    protected int[] playerUIDs;
}

And parsing the JSON from the request parameter name, like this:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        Gson gson = new Gson();
        Enumeration en = request.getParameterNames();
        GameStart start = null;
        while (en.hasMoreElements()) {
            start = gson.fromJson((String) en.nextElement(), GameStart.class);
        }
        log.info(start.gameID);
        log.info(String.valueOf(start.nrOfPlayers));
        log.info(start.playerUIDs[0] +" "+ start.playerUIDs[1]);
}

Now all values are there, but this seems more like a hack (reading JSON from request parameter name) than an elegant solution, so I thought I'd ask you guys what exactly would be the "correct" way of doing this? Am I missing something obvious?

Thanks in advance!

like image 553
Tõnis Pool Avatar asked Mar 22 '12 20:03

Tõnis Pool


People also ask

How do you parse a JSON object in Java?

We can convert a JSON to Java Object using the readValue() method of ObjectMapper class, this method deserializes a JSON content from given JSON content String.

How do you handle an array of JSON in Java?

String value = (String) jsonObject. get("key_name"); Just like other element retrieve the json array using the get() method into the JSONArray object.


1 Answers

You aren't use JSON to send data to the server:

data : myData,

This specifies parameters as a JavaScript object, but not necessarily as JSON. What this means is that if you do a GET request with:

data: {name1: "value1", name2: "value2"}

The request will be:

http://some/page?name1=value1&name2=value2

This is basically what you're seeing with your first calls, where everything is being converted to a string, then sent as a form parameter.

What you're doing in the second version is almost what you're supposed to do. The only difference is that you need to use a JavaScript object as the parameter to data, not just a string:

data: {arbitraryNameHere: JSON.stringify(myData)}

This will post your "myData" object as JSON, in the parameter named "arbitraryNameHere".

like image 125
Brendan Long Avatar answered Sep 18 '22 10:09

Brendan Long