Search code examples
javaserializationjacksonfasterxml

Converting Object into "something else" before Serializing it using FasterXML Jackson


public void serialize(IPerson person, OutputStream output) throws Exception {}

public void deserialize(InputStream input) throws Exception {}

I have an interface named IPerson, it has basic functionality.

I want to serialize the person object and be able to deserialize it from the deserialize method.

However, the scenario is this I cannot use Java's serializable interface as I can't be sure what implementation of IPerson will be used.

I have chosen to use Jackson's FasterXML, using ObjectMapper m = new ObjectMapper();

The problem I am having is that since IPerson is an interface I cannot serialize it directly using mapper.writerValue(output, person), I figured I must convert this object into something else, say a ByteArray then serialize it?

Also, this would be converting this something else into an object when deserializing? I have minimal experience with what exactly I should convert this object to and how to do so? Any ideas?


Solution

  • When using the default ObjectMapper you will have to make sure the objects you serialize are Java Beans. For non-bean classes you can set field visibility using m.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); or annotate your class using @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY).

    For deserializing you will have to tell the ObjectMapper the target type. This can be done by providing a concrete implementation type to readValue or by storing the classname within the exported JSON. For this you can set m.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "__class"); and annotate your objects with @JsonTypeInfo

    ObjectMapper om = new ObjectMapper();
    om.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "__class");
    
    IPerson value = new MyPerson();
    String s = om.writeValueAsString(value);
    IPerson d = om.readValue(s, IPerson.class);
    

    using

    interface IPerson {
       void doSomething();
    }
    
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "__class")
    @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
    class MyPerson implements IPerson {
        String name;
    
        @Override
        public void doSomething() {
        }
    }
    

    Note that, you will need a default constructor for this to work or work with @JsonCreator and @JsonProperty (see jackson-annotations for details)