jqGrid - Parsing json response

10,183

You use jqGrid option in the wrong way. It's important to understand that jqGrid need "to know" some parameters like url and datatype. If datatype is not specified the default value "xml" will be used.

You should not overwrite parameters with respect of ajaxGridOptions which already exist in jqGrid. So you should use jqGrid correctly. If URL "../rush-controller-testing/userAccount/find" returns the data in the format which you included in parsedResponse then you code could be about the following:

myGrid.jqGrid({
    url: "../rush-controller-testing/userAccount/find",
    datatype: "json",
    mtype: "POST",
    pager: "#useraccount-search-datagrid-pager",
    serializeGridData : function(data) {
        // the function is DUMMY. it MUST be replaced
        return '{"SearchCriteria": {"keyword":"emai","orderByField":"userName","sortOrder":"DESC","pagination":{"pageSize":"10","pageNumber":"2"}}}';
    },
    ajaxGridOptions: { contentType: "application/json; charset=utf-8" },
    colModel: [
        { name: 'id', key: true, width: 100 }
        { name: 'name', width: 400 }
    ],
    jsonReader: {
        root: "myData",
        page: "currentPage",
        records: "totalRecords",
        repeatitems: false
    },
    rowNum: 3,
    gridview: true,
    autoencode: true,
    viewrecords: true,
    height: "auto",
    ignoreCase: true,
    hidegrid: false
});

The usage of repeatitems: false property inside of jsonReader is really required. I don't think that you will need to use any converters of jQuery.ajax.

Share:
10,183
Rafa
Author by

Rafa

I am an energetic team member who is always up for a challenge. I am in love with technology and pleased to pursue a common goal. From my perspective, software development is much more than just coding; it is a complex ecosystem where people, technology, responsibilities and wishes coexist together.

Updated on June 04, 2022

Comments

  • Rafa
    Rafa almost 2 years

    I have a jqGrid which sends ajax requests to my server. However, my server sends a json response in a totally different format (I can not change it). Therefore I need to parse the response from my server, so my jqGrid can display the data properly.

    If I understood right, I can use ajaxGridOptions with converters. So, I can capture the response and parse it. It seems to me that converters is working fine and parsing the response properly. However, jqGrid does not understand my parsed response. It displays a message “Loading…” forever (I can see in firebug that the request/response is fine and there are no javascript error in the console).

    Can anybody help me with this?

    Here is my code:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html><head>
        <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/redmond/jquery-ui.css" />
        <link rel="stylesheet" type="text/css" href="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/css/ui.jqgrid.css" />
    </head><body>
    
    <!-- IMPORT JS -->  
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
        <script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/i18n/grid.locale-en.js"></script>
        <script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/jquery.jqGrid.min.js"></script>    
    
    <script>
    
    $(document).ready(function() {
        var parsedResponse = '{"currentPage" : "1", "totalRecords" : 5, "pageSize" : 3,'
                + '"myData" :[{"id" : "1", "name" : "Name 1" },'
                + '          { "id" : "3", "name" : "Name 3" },'
                + '          { "id" : "2", "name" : "Name 2" }]'
                + '}';
    
        var myGrid = $('<table>').attr( "id", "useraccount-search-datagrid");
        var myPager = $("<div>").attr("id", "useraccount-search-datagrid-pager");
    
        $("body").append(myGrid, myPager);
    
        myGrid.jqGrid({
            pager : myPager,
            // datastr: parsedResponse, // If I use these parameters and remove ajaxGridOptions then it will work fine with the local data
            // datatype : "jsonstring", // If I use these parameters and remove ajaxGridOptions then it will work fine with the local data
            serializeGridData : function(data) {
                return '{"SearchCriteria": {"keyword":"emai","orderByField":"userName","sortOrder":"DESC","pagination":{"pageSize":"10","pageNumber":"2"}}}';
            },
            ajaxGridOptions: {
                url: "../rush-controller-testing/userAccount/find",
                type: "POST",
                contentType: "application/json; charset=utf-8",         
                dataType: "json",
                converters: { "text json": function (responseText) {
                        // console.log(responseText); // Shows the response string from the cerver
                        return parsedResponse;
                    }
                },
                success: function(data, textStatus, jqXHR ) {
                    // Nice! It shows 'parsedResponse' from 'converters'. Looks good so far.
                    console.log(data); console.log(textStatus); console.log(jqXHR);
                }
            },
            colModel : [
                { name : 'name', index : 'id', width : "500"}
            ],
            jsonReader: {
                root: "myData", page: "currentPage", records: "totalRecords" 
            },
            rowNum : 3,
            viewrecords : true,
            height : "auto",
            ignoreCase : true,
            hidegrid: false
        });
    
    }); 
    </script>
    </body>
    </html>
    

    === UPDATE ===

    My server response is something like:

    {"UserAccountSearchResult":{
        "userAccounts":[{
            "userAccountId":18,
            "clientAccount":{"clientAccountId":19,"name":"name:5791","firstName":"firstName:5791","lastName":"lastName:5791","active":true},
            "userName":"[email protected]",
            "password":"password824504",
            "firstName":"firstName824504",
            "lastName":"lastName824504",
            "isActive":true,
            "phoneNumbers":{"phoneNumberId":36,"number":824504824504},
            "addresses":{"addressId":126,"country":"CANADA","provinceOrState":"ONTARIO","address":"address824504","city":"Windsor","postalCode":"postalCode824504"},
            "emails":{"emailId":36,"email":"[email protected]"}
            },{
            "userAccountId":44,
            "clientAccount":{"clientAccountId":45,"name":"name:3136","firstName":"firstName:3136","lastName":"lastName:3136","active":true},
            "userName":"[email protected]",
            "password":"password796312",
            "firstName":"firstName796312",
            "lastName":"lastName796312",
            "isActive":true,
            "phoneNumbers":{"phoneNumberId":88,"number":796312796312},
            "addresses":{"addressId":298,"country":"CANADA","provinceOrState":"ONTARIO","address":"address796312","city":"Greater Sudbury","postalCode":"postalCode796312"},
            "emails":{"emailId":88,"email":"[email protected]"}
            }]
        ,"pagination":{"pageSize":10,"pageNumber":2,"totalItems":49}}}
    

    So, I already have a function to parse this response to something like below. And I want to use this parsed response with jqGrid because in my application there many cases like that:

    {"currentPage" : "1",   "totalRecords" : 2, "pageSize" : 3,
        "myData" :[{
            "id" : "1", "name" : "firstName824504", "email" : "[email protected]"
        },{
            "id" : "3", "name" : "firstName796312", "email" : "[email protected]"
        }]
    };
    

    === FINAL CODE ===

    I got it working. Thanks for the help. Here is my functional example. I hope it can help somebody else in the future.

    $(document).ready(function() {
        /*
         * Here I will have a very complex logic to parse the response from the server in something jqGrid can understand.
         * Right now it is just a hard-coded string to make thinks easer to understand
         */ 
        function parseResponse(responseText){
            var parsedResponse = '{"currentPage" : "1", "totalRecords" : 5, "pageSize" : 3, "pageTotal" : 2,'
                    + '"myData" :[{"id" : "1", "name" : "Name 1" },'
                    + '          { "id" : "3", "name" : "Name 3" },'
                    + '          { "id" : "2", "name" : "Name 2" }]'
                    + '}';  
            return JSON.parse(parsedResponse);
        };
    
        var myGrid = $('<table>').attr( "id", "useraccount-search-datagrid");
        var myPager = $("<div>").attr("id", "useraccount-search-datagrid-pager");
    
        $("body").append(myGrid, myPager);
    
        myGrid.jqGrid({
            pager : myPager,
            // datastr: parsedResponse, // If I use these parameters and remove ajaxGridOptions then it will work fine with the local data
            datatype : "json",
            url: "../rush-controller-testing/userAccount/find",
            mtype: "POST",
            serializeGridData : function(data) {
                // That is just a hard-coded example to make things easier to understand. Will change it to a more complex logic later.
                return '{"SearchCriteria": {"keyword":"emai","orderByField":"userName","sortOrder":"DESC","pagination":{"pageSize":"10","pageNumber":"3"}}}';
            },
            ajaxGridOptions: {
                contentType: "application/json; charset=utf-8",
            },
            colModel : [
                { name : 'name', index : 'name', width : "500"}
            ],
            jsonReader: {
                repeatitems: false,
                root: function(data){
                    //the actual data
                    var result = parseResponse(data);
                    return result.myData;
                },
                total: function(data) {
                    //total pages for the query
                    var result = parseResponse(data);
                    return result.pageTotal;
                },
                page: function(data){
                    //current page of the query
                    var result = parseResponse(data);
                    return result.currentPage;
                },
                records: function(data){
                    //total number of records for the query
                    var result = parseResponse(data);
                    return result.totalRecords;
                } 
            },
            rowNum : 3,
            viewrecords : true,
            height : "auto",
            ignoreCase : true,
            hidegrid: false
        });
    
    });
    
  • Rafa
    Rafa about 11 years
    thank you very much for your detailed answer. I am going to try these changes and let you know very soon. (By the way, you have written many other good answers on stackoverflow, thanks for the contribution).
  • Oleg
    Oleg about 11 years
    @YoriKusanagi: You are welcome! I'm glad that my old answers could help you too. By the way, in many cases one can use prmNames option to customize the parameters which will be send to the server. serializeGridData is only the last step of transformation of the information.
  • Rafa
    Rafa about 11 years
    at this point, my real challenge is to parse the response from the server. I've been working on this for many hours and could not figure out what is going wrongly. Any help would be highly appreciated.
  • Rafa
    Rafa about 11 years
    I've tried using jsonReader but it did not work in my case. The data sent from the server is very different. Therefore, I need a complex parsing function to handle it.
  • Oleg
    Oleg about 11 years
    @YoriKusanagi: Sorry, but I don't understand this. jQuery.ajax parse the JSON response automatically it use code which use native implemented by the most web browsers. So one don't need parse the server response manually.
  • Rafa
    Rafa about 11 years
    My apologies if my post was unclear. I do't meant "parsing to JSON" this is easy to achieve, I need to parse the response to a totally different structure. I just added an response example in my question. Hopefully, it can make things clear.
  • Oleg
    Oleg about 11 years
    @YoriKusanagi: OK! First of all you don't need to make any transformation in the most cases. jqGrid provide very flexible way of reading the data. You can use functions inside of jsonReader. For example root: function (obj) { return obj.UserAccountSearchResult.userAccounts; }. In your case root: "UserAccountSearchResult.userAccounts" will be enough. You can use jsonmp as dotted string or as a function too. So You will be able to read the data from the JSON directly. If you do need to change the response before it will be processed by jaGrid you can use beforeProcessing callbacl.
  • Oleg
    Oleg about 11 years
    @YoriKusanagi: Another problem in your code: you use success callback inside of ajaxGridOptions. In the way you overwrite the method which uses jqGrid to process the response. So no results will be displayed. You should remove both converters and success callbacks. You can use loadComplete callback if needed. For email column you can use jsonmap: "emails.email". I don't see any reason to rename firstName property to name, but if it really needed you can use jsonmap: "firstName" as additional property for "name" column.