BAEL-7335: Polymorphism with Gson (#16320)
This commit is contained in:
parent
eead7a451c
commit
e4c43225b9
|
@ -0,0 +1,5 @@
|
||||||
|
package com.baeldung.gson.polymorphic;
|
||||||
|
|
||||||
|
public interface Shape {
|
||||||
|
double getArea();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.gson.polymorphic;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class ShapeTypeAdapter implements JsonSerializer<Shape>, JsonDeserializer<Shape> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Shape shape, Type type, JsonSerializationContext context) {
|
||||||
|
JsonElement elem = new Gson().toJsonTree(shape);
|
||||||
|
elem.getAsJsonObject().addProperty("type", shape.getClass().getName());
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
|
||||||
|
JsonObject jsonObject = json.getAsJsonObject();
|
||||||
|
String typeName = jsonObject.get("type").getAsString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<? extends Shape> cls = (Class<? extends Shape>) Class.forName(typeName);
|
||||||
|
return new Gson().fromJson(json, cls);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new JsonParseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package com.baeldung.gson.polymorphic;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class TypeAdapterUnitTest {
|
||||||
|
@Test
|
||||||
|
void testSerialize() {
|
||||||
|
List<Shape> shapes = Arrays.asList(
|
||||||
|
new Circle(4d),
|
||||||
|
new Square(5d)
|
||||||
|
);
|
||||||
|
|
||||||
|
GsonBuilder builder = new GsonBuilder();
|
||||||
|
builder.registerTypeHierarchyAdapter(Shape.class, new ShapeTypeAdapter());
|
||||||
|
Gson gson = builder.create();
|
||||||
|
|
||||||
|
String json = gson.toJson(shapes);
|
||||||
|
|
||||||
|
assertEquals("[" +
|
||||||
|
"{" +
|
||||||
|
"\"radius\":4.0," +
|
||||||
|
"\"area\":50.26548245743669," +
|
||||||
|
"\"type\":\"com.baeldung.gson.polymorphic.TypeAdapterUnitTest$Circle\"" +
|
||||||
|
"},{" +
|
||||||
|
"\"side\":5.0," +
|
||||||
|
"\"area\":25.0," +
|
||||||
|
"\"type\":\"com.baeldung.gson.polymorphic.TypeAdapterUnitTest$Square\"" +
|
||||||
|
"}]", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeserializeWrapper() {
|
||||||
|
List<Shape> shapes = Arrays.asList(
|
||||||
|
new Circle(4d),
|
||||||
|
new Square(5d)
|
||||||
|
);
|
||||||
|
|
||||||
|
GsonBuilder builder = new GsonBuilder();
|
||||||
|
builder.registerTypeHierarchyAdapter(Shape.class, new ShapeTypeAdapter());
|
||||||
|
Gson gson = builder.create();
|
||||||
|
|
||||||
|
String json = gson.toJson(shapes);
|
||||||
|
|
||||||
|
Type collectionType = new TypeToken<List<Shape>>(){}.getType();
|
||||||
|
List<Shape> result = gson.fromJson(json, collectionType);
|
||||||
|
|
||||||
|
assertEquals(shapes, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Square implements Shape {
|
||||||
|
private final double side;
|
||||||
|
private final double area;
|
||||||
|
|
||||||
|
public Square(double side) {
|
||||||
|
this.side = side;
|
||||||
|
this.area = side * side;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getArea() {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Square square = (Square) o;
|
||||||
|
return Double.compare(square.side, side) == 0 && Double.compare(square.area, area) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(side, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Circle implements Shape {
|
||||||
|
private final double radius;
|
||||||
|
|
||||||
|
private final double area;
|
||||||
|
|
||||||
|
public Circle(double radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
this.area = Math.PI * radius * radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getArea() {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Circle circle = (Circle) o;
|
||||||
|
return Double.compare(circle.radius, radius) == 0 && Double.compare(circle.area, area) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(radius, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.baeldung.gson.polymorphic;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class TypeFieldUnitTest {
|
||||||
|
@Test
|
||||||
|
void testSerialize() {
|
||||||
|
List<Shape> shapes = Arrays.asList(
|
||||||
|
new Circle(4d),
|
||||||
|
new Square(5d)
|
||||||
|
);
|
||||||
|
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String json = gson.toJson(shapes);
|
||||||
|
|
||||||
|
assertEquals("[" +
|
||||||
|
"{" +
|
||||||
|
"\"type\":\"circle\"," +
|
||||||
|
"\"radius\":4.0," +
|
||||||
|
"\"area\":50.26548245743669" +
|
||||||
|
"},{" +
|
||||||
|
"\"type\":\"square\"," +
|
||||||
|
"\"side\":5.0," +
|
||||||
|
"\"area\":25.0" +
|
||||||
|
"}]", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Square implements Shape {
|
||||||
|
private final String type = "square";
|
||||||
|
private final double side;
|
||||||
|
private final double area;
|
||||||
|
|
||||||
|
public Square(double side) {
|
||||||
|
this.side = side;
|
||||||
|
this.area = side * side;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getArea() {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Circle implements Shape {
|
||||||
|
private final String type = "circle";
|
||||||
|
private final double radius;
|
||||||
|
|
||||||
|
private final double area;
|
||||||
|
|
||||||
|
public Circle(double radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
this.area = Math.PI * radius * radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getArea() {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package com.baeldung.gson.polymorphic;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class WrapperUnitTest {
|
||||||
|
@Test
|
||||||
|
void testSerializeWrapper() {
|
||||||
|
List<Wrapper> shapes = Arrays.asList(
|
||||||
|
new Wrapper(new Circle(4d)),
|
||||||
|
new Wrapper(new Square(5d))
|
||||||
|
);
|
||||||
|
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String json = gson.toJson(shapes);
|
||||||
|
|
||||||
|
assertEquals("[" +
|
||||||
|
"{" +
|
||||||
|
"\"circle\":{" +
|
||||||
|
"\"radius\":4.0," +
|
||||||
|
"\"area\":50.26548245743669" +
|
||||||
|
"}" +
|
||||||
|
"},{" +
|
||||||
|
"\"square\":{" +
|
||||||
|
"\"side\":5.0," +
|
||||||
|
"\"area\":25.0" +
|
||||||
|
"}" +
|
||||||
|
"}]", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeserializeWrapper() {
|
||||||
|
List<Wrapper> shapes = Arrays.asList(
|
||||||
|
new Wrapper(new Circle(4d)),
|
||||||
|
new Wrapper(new Square(5d))
|
||||||
|
);
|
||||||
|
|
||||||
|
Gson gson = new Gson();
|
||||||
|
String json = gson.toJson(shapes);
|
||||||
|
|
||||||
|
Type collectionType = new TypeToken<List<Wrapper>>(){}.getType();
|
||||||
|
List<Wrapper> result = gson.fromJson(json, collectionType);
|
||||||
|
|
||||||
|
assertEquals(shapes, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Square implements Shape {
|
||||||
|
private final double side;
|
||||||
|
private final double area;
|
||||||
|
|
||||||
|
public Square(double side) {
|
||||||
|
this.side = side;
|
||||||
|
this.area = side * side;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getArea() {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Square square = (Square) o;
|
||||||
|
return Double.compare(square.side, side) == 0 && Double.compare(square.area, area) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(side, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Circle implements Shape {
|
||||||
|
private final double radius;
|
||||||
|
|
||||||
|
private final double area;
|
||||||
|
|
||||||
|
public Circle(double radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
this.area = Math.PI * radius * radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getArea() {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Circle circle = (Circle) o;
|
||||||
|
return Double.compare(circle.radius, radius) == 0 && Double.compare(circle.area, area) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(radius, area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Wrapper {
|
||||||
|
private final Circle circle;
|
||||||
|
private final Square square;
|
||||||
|
|
||||||
|
public Wrapper(Circle circle) {
|
||||||
|
this.circle = circle;
|
||||||
|
this.square = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wrapper(Square square) {
|
||||||
|
this.square = square;
|
||||||
|
this.circle = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Circle getCircle() {
|
||||||
|
return circle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Square getSquare() {
|
||||||
|
return square;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Wrapper wrapper = (Wrapper) o;
|
||||||
|
return Objects.equals(circle, wrapper.circle) && Objects.equals(square, wrapper.square);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(circle, square);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue