Menu

ClassCastException on deserialization

Help
Olivier Z.
2007-07-04
2013-04-29
  • Olivier Z.

    Olivier Z. - 2007-07-04

    I have a JSON string like this:
    {"sectionIdStats":"","cdArtist":"xyz","length":220,"sectionId":11,"cdTitle":"track #12","comment":"","clipBase":"/3/2/2/1/075596061223-1-5","dates":"","id":{"value":33012},"discNumber":1,"pickflag":"","trackNumber":12,"idValue":33012}

    The object I am deserializng this into has the following setters:
        public void setSectionId(int id)
        {
            //...
        }

        public void setSectionId(String id)
        {
                  //...
        }

    (from past experience it seems that I need both -- not sure why but that's another issue it seems).

    When I call JSONObject.fromString()

    I get:
    com.[snipsnip].musicops.json.JsonUtil$JsonSerializationException: Error in Deserialization of class com.[snipsnip].mgpi2.model.classical.ClassicalTrack for JSONObject: {"sectionIdStats":"","cdArtist":"XYZ","length":220,"sectionId":11,"cdTitle":"track #12","comment":"","clipBase":"/3/2/2/1/075596061223-1-5","dates":"","id":{"value":33012},"discNumber":1,"pickflag":"","trackNumber":12,"idValue":33012} -- java.lang.IllegalArgumentException: Cannot invoke com.[snipsnip].mgpi2.model.classical.ClassicalTrack.setSectionId - java.lang.ClassCastException@bb12
            at com.[snipsnip].musicops.json.JsonUtil.deserialize(JsonUtil.java:299)
            at com.[snipsnip].musicops.json.JsonUtil.deserialize(JsonUtil.java:323)
            at com.[snipsnip].mgpi2.model.classical.ClassicalModelTest.testAssignTrackSection(ClassicalModelTest.java:554)
    Caused by: net.sf.json.JSONException: java.lang.IllegalArgumentException: Cannot invoke com.[snipsnip].mgpi2.model.classical.ClassicalTrack.setSectionId - java.lang.ClassCastException@bb12
            at net.sf.json.JSONObject.toBean(JSONObject.java:682)
            at net.sf.json.JSONObject.toBean(JSONObject.java:554)
            at com.[snipsnip].musicops.json.JsonUtil.deserialize(JsonUtil.java:295)
            ... 67 more
    Caused by: java.lang.IllegalArgumentException: Cannot invoke com.[snipsnip].mgpi2.model.classical.ClassicalTrack.setSectionId - java.lang.ClassCastException@bb12
            at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
            at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
            at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
            at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
            at org.apache.commons.beanutils.PropertyUtils.setProperty(PropertyUtils.java:559)
            at net.sf.json.JSONObject.setProperty(JSONObject.java:781)
            at net.sf.json.JSONObject.setProperty(JSONObject.java:761)
            at net.sf.json.JSONObject.toBean(JSONObject.java:638)
            ... 69 more

    Besides the "why is this happening", is there a way to gather more information on which Class it was trying to cast into what?

    Thanks.

     
    • aalmiray

      aalmiray - 2007-07-05

      It looks like you have a property with two setters, the PropertyDescriptor will try its best to determine which is the correct pair of methods for read/write, which I think will be the ones that match the return type with the set type (I'm assuming the return type of sectionId is int). Following that train of thought I created a bean with two properties (int,String) which will have their appropriate setter/getter and an extra setter with another type, so far the tests are green with the latest version from cvs. So either there was a bug that has been corrected or I misunderstood your problem. I'm attaching the code for your perusal.

      public class Bean {
         private int integer;
         private String string;

         public int getInteger() {return integer;}
         public String getString() {return string;}
         public void setInteger( int integer ) {this.integer = integer;}
         public void setInteger( String integer )
         {this.integer = new Integer( integer ).intValue();}
         public void setString( int string )
         {this.string = String.valueOf( string );}
         public void setString( String string )
         {this.string = string;}
      }

      import junit.framework.TestCase;
      import net.sf.json.JSONObject;

      public class TestBean extends TestCase {
         public void testBean_from_json1() {
            JSONObject json = JSONObject.fromObject( "{'integer':11,'string':12}" );
            Bean b = (Bean) JSONObject.toBean( json, Bean.class );
            assertBean( b );
         }

         public void testBean_from_json2() {
            JSONObject json = JSONObject.fromObject( "{'integer':'11','string':'12'}" );
            Bean b = (Bean) JSONObject.toBean( json, Bean.class );
            assertBean( b );
         }

         public void testBean_with_integers() {
            Bean bean = new Bean();
            bean.setInteger( 11 );
            bean.setString( 12 );
            JSONObject json = JSONObject.fromObject( bean );
            Bean b = (Bean) JSONObject.toBean( json, Bean.class );
            assertBean( b );
         }

         public void testBean_with_strings() {
            Bean bean = new Bean();
            bean.setInteger( "11" );
            bean.setString( "12" );
            JSONObject json = JSONObject.fromObject( bean );
            Bean b = (Bean) JSONObject.toBean( json, Bean.class );
            assertBean( b );
         }

         private void assertBean( Bean b ) {
            assertEquals( 11, b.getInteger() );
            assertEquals( "12", b.getString() );
         }
      }

       
    • Olivier Z.

      Olivier Z. - 2007-07-05

      thanks for the reply. Your test case matches my situation except for the fact that the sectionId which figures as an int in the Json string is actually a class itself with setters. So maybe the introspection doesn't go 'deep enough' or as you said there was a bug that has been fixed. I tried the 2.02a but found some backward compatibility problems so I didn't pursue it.

      However, the best thing would be for the ClassCastException message to be more explicit so I can determine what type it is trying (I assume it is 'int' but I cannot be sure) and which method(s) it is trying. Is it possible to turn o some verbose mode that would indicate all this?

      Thanks.

       
    • aalmiray

      aalmiray - 2007-07-06

      Hmmm can you send a sample of your code to get more insight? it seems like PropetyUtils catches an IllegalArgumentException and throws a ClassCastException, which is later wrapped in a JSONException, meaning that perhaps there may be an opportunity to know more about the error.

       
    • Olivier Z.

      Olivier Z. - 2007-07-10

      can I reach you by email? That'll be easier if we start exchanging code. I sent you an email through your sourceforge account, or you can do the same through my sourceforge account.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.