Search code examples
javajsonjacksonpolymorphismobjectmapper

Jackson polymorphic serialization: how to remove super type property wrapper?


I have this situation:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
        @JsonSubTypes.Type(value = FlyingCar.class, name = "flying_car"),
        @JsonSubTypes.Type(value = WaterProofPhone.class, name = "water_proof_phone"),
        @JsonSubTypes.Type(value = ElectricBicycle.class, name = "electric_bicycle")
})
public abstract class Product {
}

and every subclass is defined like:

@JsonTypeName("flying_car")
public class FlyingCar extends Product {
     private double verticalSpeed; 
     private String name;
}

When I serialize the class below, I would like to not include a product property in the json:

public class Cart {
   private long id;
   private LocalDateTime date;
   private Product product;
}

Example serializing this configuration:

Product product = new FlyingCar(123.5,"StarShip");
Cart cart = new Cart();
cart.setProduct(product);

String json = objectMapper.writeValueAsString(cart);

Produces this json:

{
  "id":..,
  "product": { <--- How can I remove this wrapper ?
    "flying_car":{
      "vertical_speed": 123.5,
      "name": "StarShip"
    }
  }
}

How to simply have a json like this, without the supertype wrapper?

{
  "id":..,
  "flying_car":{
      "vertical_speed": 123.5,
      "name": "StarShip"
   }
}

I tried the @JsonUnwrapped on product but it does not work as expected.

Thanks for your help


Solution

  • To complete @Nemanja's answer, I found a simpler solution using @JsonAnyGetter:

    public class Cart {
       private long id;
       private LocalDateTime date;
       @JsonIgnore
       private Product product;
    
       @JsonAnyGetter
       Map<String, Product> determineProduct(){
         if (this.product instanceof FlyingCar){
           return Map.of("flying_car", this.product);
         }
         ....other type checking
      }
    }
    

    It's a bit simpler and we don't have to define a custom serializer