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