From bfc63c6eeb52067d26ad7e57c57348e46253b5da Mon Sep 17 00:00:00 2001 From: ovidiumihaitacu <138307181+ovidiumihaitacu@users.noreply.github.com> Date: Mon, 31 Jul 2023 20:19:16 +0300 Subject: [PATCH] [BAEL-6750] - Jackson Polymorphic Deserialization and SubTypes registration using Reflection API (#14503) * [BAEL-6750] - Jackson Polymorphic Deserialization and SubTypes registration using Reflection API * Renamed test files --------- Co-authored-by: ovidiu-mihai98 <57233636+ovidiu-mihai98@users.noreply.github.com> --- .../pom.xml | 43 ++++++++++++ .../deserialization/reflection/Vehicle.java | 47 +++++++++++++ .../reflection/VehicleSubType.java | 13 ++++ .../typeHandlingAnnotations/Vehicle.java | 66 +++++++++++++++++++ .../reflection/ReflectionUnitTest.java | 43 ++++++++++++ .../TypeHandlingAnnotationsUnitTest.java | 20 ++++++ jackson-modules/pom.xml | 1 + 7 files changed, 233 insertions(+) create mode 100644 jackson-modules/jackson-polymorphic-deserialization/pom.xml create mode 100644 jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/Vehicle.java create mode 100644 jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/VehicleSubType.java create mode 100644 jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/Vehicle.java create mode 100644 jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/reflection/ReflectionUnitTest.java create mode 100644 jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/TypeHandlingAnnotationsUnitTest.java diff --git a/jackson-modules/jackson-polymorphic-deserialization/pom.xml b/jackson-modules/jackson-polymorphic-deserialization/pom.xml new file mode 100644 index 0000000000..afa9cab82f --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + jackson-polymorphic-deserialization + jackson-polymorphic-deserialization + + + com.baeldung + jackson-modules + 0.0.1-SNAPSHOT + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-core.version} + + + org.reflections + reflections + ${reflections.version} + + + + + jackson-polymorphic-deserialization + + + src/main/resources + true + + + + + + 2.15.2 + 0.9.11 + + + \ No newline at end of file diff --git a/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/Vehicle.java b/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/Vehicle.java new file mode 100644 index 0000000000..54f4cb7405 --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/Vehicle.java @@ -0,0 +1,47 @@ +package com.baeldung.jackson.polymorphic.deserialization.reflection; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true) +public class Vehicle { + + public String type; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @VehicleSubType("ELECTRIC_VEHICLE") + public static class ElectricVehicle extends Vehicle { + + String autonomy; + String chargingTime; + + public String getAutonomy() { + return autonomy; + } + + public void setAutonomy(String autonomy) { + this.autonomy = autonomy; + } + + public String getChargingTime() { + return chargingTime; + } + + public void setChargingTime(String chargingTime) { + this.chargingTime = chargingTime; + } + } + + @VehicleSubType("FUEL_VEHICLE") + public static class FuelVehicle extends Vehicle { + + String fuelType; + String transmissionType; + } +} diff --git a/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/VehicleSubType.java b/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/VehicleSubType.java new file mode 100644 index 0000000000..0280d465c7 --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/reflection/VehicleSubType.java @@ -0,0 +1,13 @@ +package com.baeldung.jackson.polymorphic.deserialization.reflection; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface VehicleSubType { + + String value(); +} diff --git a/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/Vehicle.java b/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/Vehicle.java new file mode 100644 index 0000000000..8d858893f1 --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/src/main/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/Vehicle.java @@ -0,0 +1,66 @@ +package com.baeldung.jackson.polymorphic.deserialization.typeHandlingAnnotations; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true) +@JsonSubTypes({ + @JsonSubTypes.Type(value = Vehicle.ElectricVehicle.class, name = "ELECTRIC_VEHICLE"), + @JsonSubTypes.Type(value = Vehicle.FuelVehicle.class, name = "FUEL_VEHICLE") +}) +public class Vehicle { + + public String type; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public static class ElectricVehicle extends Vehicle { + + String autonomy; + String chargingTime; + + public String getAutonomy() { + return autonomy; + } + + public void setAutonomy(String autonomy) { + this.autonomy = autonomy; + } + + public String getChargingTime() { + return chargingTime; + } + + public void setChargingTime(String chargingTime) { + this.chargingTime = chargingTime; + } + } + + public static class FuelVehicle extends Vehicle { + + String fuelType; + String transmissionType; + + public String getFuelType() { + return fuelType; + } + + public void setFuelType(String fuelType) { + this.fuelType = fuelType; + } + + public String getTransmissionType() { + return transmissionType; + } + + public void setTransmissionType(String transmissionType) { + this.transmissionType = transmissionType; + } + } +} diff --git a/jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/reflection/ReflectionUnitTest.java b/jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/reflection/ReflectionUnitTest.java new file mode 100644 index 0000000000..78b462750a --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/reflection/ReflectionUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.jackson.polymorphic.deserialization.reflection; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Set; + +import org.junit.jupiter.api.Test; +import org.reflections.Reflections; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.jsontype.NamedType; + +public class ReflectionUnitTest { + + @Test + public void whenDeserializingPolymorphic_thenCorrect() throws JsonProcessingException { + String json = "{\"type\":\"ELECTRIC_VEHICLE\",\"autonomy\":\"500\",\"chargingTime\":\"200\"}"; + ObjectMapper objectMapper = getCustomObjectMapper(); + + Vehicle vehicle = objectMapper.readValue(json, Vehicle.class); + + assertEquals(Vehicle.ElectricVehicle.class, vehicle.getClass()); + } + + private ObjectMapper getCustomObjectMapper() { + + ObjectMapper objectMapper = new ObjectMapper(); + + Reflections reflections = new Reflections("com.baeldung.jackson.polymorphic.deserialization.reflection"); + Set> subtypes = reflections.getTypesAnnotatedWith(VehicleSubType.class); + + for (Class subType : subtypes) { + VehicleSubType annotation = subType.getAnnotation(VehicleSubType.class); + if (annotation != null) { + String typeName = annotation.value(); + objectMapper.registerSubtypes(new NamedType(subType, typeName)); + } + } + + return objectMapper; + } +} diff --git a/jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/TypeHandlingAnnotationsUnitTest.java b/jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/TypeHandlingAnnotationsUnitTest.java new file mode 100644 index 0000000000..b859331c6f --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/src/test/java/com/baeldung/jackson/polymorphic/deserialization/typeHandlingAnnotations/TypeHandlingAnnotationsUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.jackson.polymorphic.deserialization.typeHandlingAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class TypeHandlingAnnotationsUnitTest { + + @Test + public void whenDeserializingPolymorphic_thenCorrect() throws JsonProcessingException { + String json = "{\"type\":\"ELECTRIC_VEHICLE\",\"autonomy\":\"500\",\"chargingTime\":\"200\"}"; + + Vehicle vehicle = new ObjectMapper().readerFor(Vehicle.class).readValue(json); + + assertEquals(Vehicle.ElectricVehicle.class, vehicle.getClass()); + } +} diff --git a/jackson-modules/pom.xml b/jackson-modules/pom.xml index 1f4a22e379..196d0997b5 100644 --- a/jackson-modules/pom.xml +++ b/jackson-modules/pom.xml @@ -22,6 +22,7 @@ jackson-custom-conversions jackson-exceptions jackson-jr + jackson-polymorphic-deserialization