Search code examples
javaserializationjacksondeserializationobjectmapper

java jackson keep type information after serialize if variable of type Object


ClassA

public class ClassA {
   private String id;
   private Object rawData;
}

ClassB

public class ClassB {
   private String name;
}

ClassC

public class ClassC {
   String address;
}

Main Class

public class MainExample {
   public static void main( String[] args ) throws IOException {

      ObjectMapper mapper = new ObjectMapper(  );

      ClassB classB = new ClassB();
      //ClassC classC = new ClassC();
      ClassA classA = new ClassA();
      classA.setRawData(  classB );
      //classA.setRawData(  classC );

      if (classA.getRawData() instanceof ClassB) {
         System.out.println("true ");
      } else {
         System.out.println("false");
      }

      String classAString = mapper.writeValueAsString( classA );
      ClassA a = mapper.readValue( classAString, ClassA.class );

      if (a.getRawData() instanceof ClassB) {
         System.out.println("true ");
      } else {
         System.out.println("false");
      }
   }
}

why first if-else printing "TRUE" and second if-else printing "false"??

How can I check the type of rawData?


Solution

  • mapper.writeValueAsString(classA) will serialise the instance into something similar to {"rawData":{}}.

    While deserialising {} the default mapper would fail, because it treats {} as a non-serializable type. If you've configured SerializationFeature.FAIL_ON_EMPTY_BEANS to false before, you will have an empty Object created.

    You might want to use mapper.enableDefaultTyping(); to include type information in JSON, and thereby deserialize into the correct types.

    NOTE: use of Default Typing can be a potential security risk if incoming content comes from untrusted sources, and it is recommended that this is either not done, or, if enabled, use setDefaultTyping passing a custom TypeResolverBuilder implementation that white-lists legal types to use.