'Deserialise object into a subtype dynamically using gson
I have a base class
public class Box<T> {
private T entity;
public T getEntity() {
return entity;
}
void setEntity(T entity) {
this.entity = entity;
}
}
It has 2 implementations.
// Class Person
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// Class Machine
public class Machine {
private String macAddress;
private String type;
public Machine(String macAddress, String type) {
this.macAddress = macAddress;
this.type = type;
}
}
If I want to serialise either of classA or class B objects, I will do it like this
Type typeTokenPerson = new TypeToken< Box <Person>>() {}.getType();
String userJson = gson.toJson(boxWithPersonObject, typeTokenPerson);
But the problem here is I need to know the type at compile time. I have a use case where I don't know this at compile-time, in other words, I have a json which I want to deserialize into either Person or Animal and I want to do this at runtime based on some condition. Is there a way to do this usig Gson ?
Example: Lets say we have a json like this
{
"entity": {
"name": "ABC",
"age": 10
}
}
This is of type Person. I want to deserialise this into an object of type Box<Person>
Solution 1:[1]
Gson can do it like this.
package com.example.demo;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
import java.time.Duration;
import java.time.LocalDateTime;
public class GsonDemo {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private <T> Box<T> parseResponse(String responseData) {
Gson gson = new Gson();
Type jsonType = new TypeToken<Box<T>>() {
}.getType();
Box<T> result = gson.fromJson(responseData, jsonType);
return result;
}
@Test
public void test() {
LocalDateTime start = LocalDateTime.now();
try {
String json = "{ \"entity\": { \"name\": \"ABC\", \"age\": 10 }}";
Box<Person> objectBox = parseResponse(json);
System.out.println(objectBox);
String json2 = "{\n \"entity\": { \"macAddress\": \"DEF\", \"type\": \"def\" }}";
Box<Machine> objectBox2 = parseResponse(json2);
System.out.println(objectBox2);
} catch (Exception e) {
logger.error("Error", e);
}
LocalDateTime end = LocalDateTime.now();
logger.info("Cost time {}", Duration.between(start, end).toMillis() + "ms");
}
public class Box<T> {
private T entity;
public T getEntity() {
return entity;
}
void setEntity(T entity) {
this.entity = entity;
}
@Override
public String toString() {
return "Box{" + "entity=" + entity + '}';
}
}
public class Person {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
public class Machine {
private String macAddress;
private String type;
public Machine(String macAddress, String type) {
this.macAddress = macAddress;
this.type = type;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Machine{" + "macAddress='" + macAddress + '\'' + ", type='" + type + '\'' + '}';
}
}
}
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 |
