'Deserialize parent/child classes with different config with Jackson

I'm working on a Restful application with Spring Boot and I've defined my classes as below:

class Organization {
    String name;
}

class Base {
    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    Organization org;
}

class Car extends Base{
  //other members
}

class FlattenCar extends Car {
    @JsonUnwrapped(prefix = "org_")
    Organization org;
}

Now what happened is, deserializing the org object depends on the first time call. It means, if I deserialize Car at the first time, next calls on deserializing FlattenCar doesn't unwrap org and vice versa. I know that I hid org member, but it seems the first time deserializing is cached! Who knows where is the problem and how can I resolve it?



Solution 1:[1]

Your problem seems to be that have in your Base class the option READ_ONLY (only for serialization), when it should be WRITE_ONLY if only want to take this property into account in the deserialization.

READ_ONLY: Access setting that means that the property may only be read for serialization, but not written (set) during deserialization.

WRITE_ONLY: Access setting that means that the property may only be written (set) for deserialization, but will not be read (get) on serialization, that is, the value of the property is not included in serialization.

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

@RestController
public class API {
    
    @Data
    public static class Organization {
        private String name;
    }

    @Data
    public static class Base {
        @JsonProperty(access = Access.WRITE_ONLY)
        private Organization org;
    }
    
    @Getter @Setter
    public static class Car extends Base {
        private String prop1;
    };
    
    @Getter @Setter
    public static class FlattenCar extends Car { 
        private String prop2;
    };
    
    @PostMapping("/car")
    public Car deserializeCar(@RequestBody Car car) {
        System.out.println("Car: " + car);
        return car;
    }
    
    @PostMapping("/flatten_car")
    public FlattenCar deserializeFlattenCar(@RequestBody FlattenCar flattenCar) {
        System.out.println("Flatten: " + flattenCar);
        return flattenCar;
    }
    
}

Ouput:

Flatten: API.Base(org=API.Organization(name=Org. Test))
Car: API.Base(org=API.Organization(name=Org. Test))

Remember that Car/CarFlatten class's to_string method has been inherit of Base class in this example.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 BiteBat