PDA

View Full Version : ClassCastException : JSONArray cannot be cast to JSONObject



garyiskidding
24 Jul 2009, 4:01 AM
I am trying to fetch json as string from my server and then use it to populate a grid.

The panels etc all render but the grid is not populated and i get this error:


load exception = com.google.gwt.json.client.JSONArray cannot be cast to com.google.gwt.json.client.JSONObject
java.lang.ClassCastException: com.google.gwt.json.client.JSONArray cannot be cast to com.google.gwt.json.client.JSONObject
at com.extjs.gxt.ui.client.data.JsonReader.read(JsonReader.java:52)
at com.extjs.gxt.ui.client.data.RpcProxy$1.onSuccess(RpcProxy.java:32)
at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:215)
at com.google.gwt.http.client.Request.fireOnResponseReceivedImpl(Request.java:264)
at com.google.gwt.http.client.Request.fireOnResponseReceivedAndCatch(Request.java:236)
at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:227)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.ie.IDispatchImpl.callMethod(IDispatchImpl.java:126)
at com.google.gwt.dev.shell.ie.IDispatchProxy.invoke(IDispatchProxy.java:155)
at com.google.gwt.dev.shell.ie.IDispatchImpl.Invoke(IDispatchImpl.java:294)
at com.google.gwt.dev.shell.ie.IDispatchImpl.method6(IDispatchImpl.java:194)
at org.eclipse.swt.internal.ole.win32.COMObject.callback6(COMObject.java:117)
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1925)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966)
at com.google.gwt.dev.SwtHostedModeBase.processEvents(SwtHostedModeBase.java:235)
at com.google.gwt.dev.HostedModeBase.pumpEventLoop(HostedModeBase.java:558)
at com.google.gwt.dev.HostedModeBase.run(HostedModeBase.java:405)
at com.google.gwt.dev.HostedMode.main(HostedMode.java:232)

My code looks like this:


//proxy
RpcProxy<String> proxy = new RpcProxy<String>() {
@Override
public void load(Object loadConfig, AsyncCallback<String> callback) {
Map requestData = new HashMap();
requestData.put("action", "testMe");
service.doService(requestData, callback);
}
};
//reader
JsonReader<ListLoadConfig> jsonReader = new JsonReader<ListLoadConfig>(AssociateModel.getModelType());

BaseListLoader loader = new BaseListLoader(proxy, jsonReader);
loader.addLoadListener(new LoadListener() {
public void loaderBeforeLoad(LoadEvent le) {
System.out.println("before load");
}
public void loaderLoad(LoadEvent le) {
System.out.println("load succeeded");
}

public void loaderLoadException(LoadEvent le) {
System.out.println("load exception = " + le.exception.getLocalizedMessage());
le.exception.printStackTrace();
}
});
//store1
final ListStore store1 = new ListStore<ModelData>(loader);
store1.addStoreListener(new StoreListener<BaseModel>() {
public void storeUpdate(StoreEvent<BaseModel> se) {
List<Record> modefied = store1.getModifiedRecords();
if (null != modefied) {
for (Record record : modefied) {
Collection propertyNames = record.getPropertyNames();
for (Iterator iterator = propertyNames.iterator(); iterator.hasNext();) {
String property= (String) iterator.next();
System.out.println("property:" + property + ",value:" + record.get(property));
}
}
}
}
});

loader.load();

and the model type is being created as:


public static ModelType getModelType(){
ModelType type = new ModelType();

type.setTotalName("totalCount");
type.setRecordName("id");

type.addField("id");
type.addField("firstName");
type.addField("lastName");
type.addField("location");
return type;
}

The json returned from the server is :


[{
"totalCount":2
},
{
"data":[{
"lastName":"lastName","location":"location","id":"id","firstName":"firstName"
},{
"lastName":"lastName2","location":"location2","id":"id2","firstName":"firstName2"
}]
}]

I get this error while loading the loader. Please suggest what could be going wrong.

sven
24 Jul 2009, 4:04 AM
You need to use JsonLoadResultReader

garyiskidding
24 Jul 2009, 4:10 AM
The only change i made was:



JsonLoadResultReader<ListLoadConfig> jsonReader = new JsonLoadResultReader<ListLoadConfig>(AssociateModel.getModelType());


and the error remains:




load exception = com.google.gwt.json.client.JSONArray cannot be cast to com.google.gwt.json.client.JSONObject
java.lang.ClassCastException: com.google.gwt.json.client.JSONArray cannot be cast to com.google.gwt.json.client.JSONObject
at com.extjs.gxt.ui.client.data.JsonReader.read(JsonReader.java:52)
at com.extjs.gxt.ui.client.data.RpcProxy$1.onSuccess(RpcProxy.java:32)
at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:215)
at com.google.gwt.http.client.Request.fireOnResponseReceivedImpl(Request.java:264)
at com.google.gwt.http.client.Request.fireOnResponseReceivedAndCatch(Request.java:236)
at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:227)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.ie.IDispatchImpl.callMethod(IDispatchImpl.java:126)
at com.google.gwt.dev.shell.ie.IDispatchProxy.invoke(IDispatchProxy.java:155)
at com.google.gwt.dev.shell.ie.IDispatchImpl.Invoke(IDispatchImpl.java:294)
at com.google.gwt.dev.shell.ie.IDispatchImpl.method6(IDispatchImpl.java:194)
at org.eclipse.swt.internal.ole.win32.COMObject.callback6(COMObject.java:117)
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1925)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966)
at com.google.gwt.dev.SwtHostedModeBase.processEvents(SwtHostedModeBase.java:235)
at com.google.gwt.dev.HostedModeBase.pumpEventLoop(HostedModeBase.java:558)
at com.google.gwt.dev.HostedModeBase.run(HostedModeBase.java:405)
at com.google.gwt.dev.HostedMode.main(HostedMode.java:232)


please suggest if i need to try with something else.

sven
24 Jul 2009, 4:12 AM
Your modeltype is also not correct. Please take a look at the JsonGridExample

garyiskidding
24 Jul 2009, 4:30 AM
Thanks for the quick reply sven,

i've modefied my ModelType per the JsonGridExample:



public static ModelType getModelType(){
ModelType type = new ModelType();
type.setTotalName("totalCount");
type.setRecordName("id");
type.addField("id", "id");
type.addField("firstName", "firstName");
type.addField("lastName", "lastName");
type.addField("location", "location");
return type;
}


the 'map' of the fields in the modeltype matches the 'id' of my ColumnConfig for the grid , like:




ColumnConfig nameColumn = new ColumnConfig();
nameColumn.setId("firstName");



I've changed the store, listener as per the example, to be :



//reader
JsonLoadResultReader<ListLoadResult<ModelData>> jsonReader = new JsonLoadResultReader<ListLoadResult<ModelData>>(AssociateModel.getModelType());

//BaseListLoader
BaseListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(proxy, jsonReader);

//store
final ListStore<ModelData> store1 = new ListStore<ModelData>(loader);



i still get the same error. Please help.

daddieke
24 Jul 2009, 7:48 AM
I also use JSON for data exchange but do my own request/response handling so I'm not really familiar with the whole loading mechanism. But based on your error message I'd say (obviously) you're trying to cast a JSONArray to JSONObject. The JSON you get from your server looks OK to me but do you correctly feed it to the reader/loader mechanism ? I suppose your intention is to use the "data" array only and not the whole response.

garyiskidding
27 Jul 2009, 1:27 AM
Yes, i am only interested in what the "data" section of the response has. But as per the json grid example, i have the 'data' element added as the root of the ModelType.

I just can't get past this error, and i think there is a small difference between how i am returning the data, and how the reader/loader would parse it into the grid.

As far as a JsonLoadResultReader, BaseListLoader and RPC are concerned:

Can anyone highlight if i could be missing something around :

1) What is the expected format of the string that should be returned from the server?
2) How should i configure my ModelType for a string thats being returned from the server

sven
27 Jul 2009, 1:54 AM
You still havent looked at the examples correctly. There is a root definition in the examples modeltype. Your modeltype is missing that, however your returned json as a root.

garyiskidding
27 Jul 2009, 2:07 AM
I'm sorry i forgot to mention in my last email, i had already changed the model type as per the example:



public static ModelType getModelType(){
ModelType type = new ModelType();


type.setRoot("records");//set the root

type.addField("id");
type.addField("firstName");
type.addField("lastName");
type.addField("location");
return type;
}


and also made changes to the json string that i am returning from the server to be more like the example. it now looks like:



[[
{
"records":[{
"lastName":"lastName","location":"location","id":"id","firstName":"firstName"
},{
"lastName":"lastName2","location":"location2","id":"id2","firstName":"firstName2"
}]
}
]]


I tied with and without these:



type.setTotalName("totalCount");
type.setRecordName("id");


but i still get the error :((. Please help...!

sven
27 Jul 2009, 2:12 AM
You have your response also inside an array. Is there a reason for this? Why you are not simply retuning:




{
"totalCount":2,
"data":[{
"lastName":"lastName","location":"location","id":"id","firstName":"firstName"
},{
"lastName":"lastName2","location":"location2","id":"id2","firstName":"firstName2"
}]
}

garyiskidding
27 Jul 2009, 2:31 AM
That indeed was the problem. I incorrectly assumed that the parsing would take care of the extra '[]'s.

You're the man..

thanks a ton..!:D

imran
6 Aug 2009, 8:13 AM
You have your response also inside an array. Is there a reason for this? Why you are not simply retuning:




{
"totalCount":2,
"data":[{
"lastName":"lastName","location":"location","id":"id","firstName":"firstName"
},{
"lastName":"lastName2","location":"location2","id":"id2","firstName":"firstName2"
}]
}



Hi sven,

There are cases where the root of the json response is not an array. Taking the following JSON for example:



{"customers":
{"customer":[
{"id":1,"name":"John"},
{"id":2,"name":"Alex"}
]}
}


GXT breaks if we setRoot to "customer" as the jsonRoot.get(modelType.getRoot()) returns null in JsonReader.java read(Object, object) method.

If we setRoot("customers") it proceeds fine until it tries to Cast into JSONArray when it's not.

In ExtJS we would be able to do something like setRoot("customers.customer"), but I don't find any way to do such a thing in GXT.

The front-end should not force a back-end service to return a toolkit specific response. The services in our environment are used by a variety of different front-end's (flex, jquery, ext, possibly gxt). Is there any workaround for this?

Any help would be greatly appreciated.

Thanks