jqGrid - Parsing json response
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.
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, 2022Comments
-
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 about 11 yearsthank 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 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 about 11 yearsat 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 about 11 yearsI'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 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 about 11 yearsMy 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 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 exampleroot: function (obj) { return obj.UserAccountSearchResult.userAccounts; }
. In your caseroot: "UserAccountSearchResult.userAccounts"
will be enough. You can usejsonmp
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 usebeforeProcessing
callbacl. -
Oleg about 11 years@YoriKusanagi: Another problem in your code: you use
success
callback inside ofajaxGridOptions
. In the way you overwrite the method which uses jqGrid to process the response. So no results will be displayed. You should remove bothconverters
andsuccess
callbacks. You can useloadComplete
callback if needed. Foremail
column you can usejsonmap: "emails.email"
. I don't see any reason to renamefirstName
property toname
, but if it really needed you can usejsonmap: "firstName"
as additional property for"name"
column.