1

I am trying to serialize and dederialize an answer from hibernate.
almost successfully.
First I get the data (object DealBean) from the DB using

Collections.checkedList(session.createCriteria(DealBean.class).add(Restrictions.eq("account", account)).list(), DealBean.class);

then I serialize it (using gson) and send the result to the client.

in the client I try to deserialize it using

Type type = new TypeToken<Collection<DealBean>>(){}.getType();
    List<DealBean> dealsForAccount = (List<DealBean>)Json.from(SomeAnswerString);

now - I get JsonParseException. I think that the list returned from the hibernate is another type java.util.Collections$CheckedRandomAccessList I get the following exception (below). 1. any suggestions? 2. am i selecting correctly ? could i cast the result at the server ?

JsonParseException: The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@a17378 failed to deserialized json object {"type":"java.util.Collections$CheckedRandomAccessList","content":"[{\"ID\":5,\"tradable\":{\"id\":5,\"tradableName\":\"Tradable1\",\"moneyMultiplier\":1},\"Action\":\"buy\",\"amount\":501.0,\"price\":50.3,\"portfolio\":{\"ID\":2,\"portfolioName\":\"Portfolio2\"},\"account\":{\"ID\":1,\"accountName\":\"Account1\",\"bank\":{\"ID\":1,\"BankName\":\"Bank1\"}},\"date\":\"12:17:36 02/01/1970\",\"activitySum\":0.0,\"aggregated\":false},{\"ID\":6,\"tradable\":{\"id\":6,\"tradableName\":\"Tradable1\",\"moneyMultiplier\":1},\"Action\":\"sell\",\"amount\":1001.0,\"price\":50.4,\"portfolio\":{\"ID\":2,\"portfolioName\":\"Portfolio2\"},\"account\":{\"ID\":2,\"accountName\":\"Account2\",\"bank\":{\"ID\":2,\"BankName\":\"Bank2\"}},\"date\":\"12:17:36 02/01/1970\",\"activitySum\":0.0,\"aggregated\":false},{\"ID\":7,\"tradable\":{\"id\":7,\"tradableName\":\"Tradable2\",\"moneyMultiplier\":1},\"Action\":\"buy\",\"amount\":502.0,\"price\":50.5,\"portfolio\":{\"ID\":2,\"portfolioName\":\"Portfolio2\"},\"account\":{\"ID\":1,\"accountName\":\"Account1\",\"bank\":{\"ID\":1,\"BankName\":\"Bank1\"}},\"date\":\"12:17:36 02/01/1970\",\"activitySum\":0.0,\"aggregated\":false},{\"ID\":8,\"tradable\":{\"id\":8,\"tradableName\":\"Tradable2\",\"moneyMultiplier\":1},\"Action\":\"sell\",\"amount\":1002.0,\"price\":50.6,\"portfolio\":{\"ID\":2,\"portfolioName\":\"Portfolio2\"},\"account\":{\"ID\":2,\"accountName\":\"Account2\",\"bank\":{\"ID\":2,\"BankName\":\"Bank2\"}},\"date\":\"12:17:36 02/01/1970\",\"activitySum\":0.0,\"aggregated\":false}]"} given the type java.util.Collection at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:63) at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:88) at com.google.gson.JsonDeserializationVisitor.visitUsingCustomHandler(JsonDeserializationVisitor.java:76) at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:98) at com.google.gson.JsonDeserializationContextDefault.fromJsonObject(JsonDeserializationContextDefault.java:73) at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:51) at com.google.gson.Gson.fromJson(Gson.java:495) at com.google.gson.Gson.fromJson(Gson.java:444) at com.google.gson.Gson.fromJson(Gson.java:396) at positions.server.services.PositionServerServicesInternalWrapperTest.testGetPositionsForPortfolio(PositionServerServicesInternalWrapperTest.java:134) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65) Caused by: java.lang.IllegalStateException: This is not a JSON Array. at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:100) at com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter.deserialize(DefaultTypeAdapters.java:468) at com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter.deserialize(DefaultTypeAdapters.java:435) at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:50) ... 31 more

List<BankBean> al = new ArrayList<BankBean>();
al.add(bank1);
al.add(bank2);
String alStr = Json.toWrap(al); // 

List<BankBean> reAl;

Gson gson = new Gson();
Type type = new TypeToken<Collection<BankBean>>(){}.getType();
List<String> listFromJson = gson.fromJson(alStr,type);
ColinD
  • 108,630
  • 30
  • 201
  • 202
Bick
  • 17,833
  • 52
  • 146
  • 251

2 Answers2

2

The type java.util.Collections$CheckedRandomAccessList is a wrapper produced by Collections.checkedList of another list that makes sure that anything added to the list matches the appropriate type signature. Unless you have some way of specifying how to create the backing list and the type (aka instance of java.lang.Class) that it is supposed to check, then there is not enough information to construct one.

To fix it, maybe change "java.util.Collections$CheckedRandomAccessList" to "java.util.ArrayList" and call Collections.checkedList on the result of your deserialization with the appropriate guard type.

And to prevent the problem from recurring, maybe do the following before serializing if your list is not an instanceof ArrayList<?>:

List<Object> mySerializableList = new ArrayList<Object>(myList);
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Hi Mike, I cant undestaand cmpletely your comment. instead of Collections.checkedList(session.createCriteria(Deal......; what should I write ? why should call Collections.checkedList on my deserialize result? is there a way to write my select that it will go directly to an arraylist? 10x. – Bick Mar 26 '11 at 22:15
  • The data in the DB cannot be deserialized since whoever inserted it, put in a checked list, not an `ArrayList`. Your SELECT is returning data that cannot be deserialized without the change I suggested: replacing `java.util....$CheckedRandomAccessList` with `java.util.ArrayList`. You don't need to worry about calling `Collections.checkedList` on the deserialized version unless you want to get as close as possible to what was put in. Depending on the database, you might be able to do the replace in your query : http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_replace – Mike Samuel Mar 26 '11 at 22:57
  • Hi Mike. I was the one who put the objects in the DB. I did not put any list but rather one object at a time. Anyhow, Does the table remember which collection I was using when I inserted the object ? Maybe, I need to elaborate a little more . Since I made some changes as you revcomended I will open a new thread. I would love it if you looked at it cause I get no results yet. I put it here http://stackoverflow.com/questions/5448043/de-serializing-generics-collection-in-gson-after-quering-from-db – Bick Mar 27 '11 at 08:40
0

JSON you have does not look like simple collection, but rather like a bean that has properties and collection. So that may need to be changed. Your JSON must match object(s) you are mapping to, regardless of library being used.

And if you can't make it work with Gson, there are others you can try out, with more powerful data binding featuers.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • Jackson (http://wiki.fasterxml.com/JacksonHome) and Flex-JSON (http://flexjson.sourceforge.net/) for example. – StaxMan Mar 26 '11 at 17:53