I had posted the question wrongly. I am posting the question correctly here ...
I am getting a json string as a HTTP response. I know the structure of it. It is as follows:
public class Json<T> {
public Hits<T> hits;
}
public class Hits<T> {
public int found;
public int start;
public ArrayList<Hit<T>> hit;
}
public class Hit<T> {
public String id;
public Class<T> data;
}
The "data" field can belong to any class. I will know it at runtime only. I will get it as a parameter. This is how I am deserializing.
public <T> void deSerialize(Class<T> clazz) {
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(jsonString, new TypeReference<Json<T>>() {});
}
But I am getting an error -
cannot access private java.lang.class.Class() from java.lang.class. Failed to set access. Cannot make a java.lang.Class constructor accessible
You will need to build JavaType
explicitly, if generic type is only dynamically available:
// do NOT create new ObjectMapper per each request!
final ObjectMapper mapper = new ObjectMapper();
public Json<T> void deSerialize(Class<T> clazz, InputStream json) {
return mapper.readValue(json,
mapper.getTypeFactory().constructParametricType(Json.class, clazz));
}
Sample generic deserializing interface:
public interface Deserializable<T> {
static final ObjectMapper mapper = new ObjectMapper();
@SuppressWarnings("unchecked")
default T deserialize(String rawJson) throws IOException {
return mapper.readValue(rawJson, (Class<T>) this.getClass());
}
}
You're serializing and deserializing Class object to JSON? Maybe keep it as String in Hit and create additional getter that launches Class.forName, e.g.
public class Hit {
public String id;
public String data;
public Class<?> getDataClass() throws Exception {
return Class.forName(data);
}
}
JSON string that needs to be deserialized will have to contain the type information about parameter T
.
You will have to put Jackson annotations on every class that can be passed as parameter T
to class Json
so that the type information about parameter type T
can be read from / written to JSON string by Jackson.
Let us assume that T
can be any class that extends abstract class Result
.
public class Json<T extends Result> {
public Hits<T> hits;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
@JsonSubTypes.Type(value = ImageResult.class, name = "ImageResult"),
@JsonSubTypes.Type(value = NewsResult.class, name = "NewsResult")})
public abstract class Result {
}
public class ImageResult extends Result {
}
public class NewsResult extends Result {
}
Once each of the class (or their common supertype) that can be passed as parameter T
is annotated, Jackson will include information about parameter T
in the JSON. Such JSON can then be deserialized without knowing the parameter T
at compile time.
This Jackson documentation link talks about Polymorphic Deserialization but is useful to refer to for this question as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With