如果我只有我的类的字符串名称,通过规范名称调用和对象的json字符串表示形式,如何从json字符串反序列化对象?
换句话说,我需要这样的方法:
public <T> T deserialize(String json, String className) {
// some code
}
我们有类名和json字符串-我们需要将json反序列化为java对象。
如果我知道对象的类,我知道如何反序列化json到对象,例如,我们可以使用Jackson
:
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Car car = objectMapper.readValue(json, Car.class);
但是在我的任务中,有一个不同的类-可能是Cat.class
,Dog.class
,Car.class
等,并且每个类的状态都不同。而且我需要 universal 方法来反序列化。
我写这样的东西:
public final class Utils implements Serializable {
private Utils () {
throw new AssertionError();
}
private static ObjectMapper objectMapper = new ObjectMapper();
public static String toJson(Object obj) {
String objectToJson;
try {
objectToJson = objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new UncheckedIOException(String.format("Can't serialize object %s to JSON string", obj), e);
}
return objectToJson;
}
public static <T> T fromJson(String json, String className) throws ClassNotFoundException, IOException {
Class<?> clz = Class.forName(className);
return (T) objectMapper.readValue(json, clz);
}
}
它适用于上面的汽车示例,但带有警告cast exception
。
但是也许有更好的方法吗?
哦,并不是所有的对象都这么简单。其中一些会封装集合和其他对象。
答案 0 :(得分:1)
问题源于编译器想要(实际上)为使用该方法的每种类型T创建此方法的不同实例。但是,论点中没有什么可以保留的。
如果调用者不知道期望的类,除了该类的String表示形式(我假设它也已经保存在JSON中?),他将如何处理的结果这个电话吗?由于他不知道,因此他必须仅将其用作Object,在这种情况下,该方法也可以简单地返回Object。
如果呼叫者确实知道该类,那么他可以传入一个类作为参数,这样您就不会有任何问题。
在撰写本文时,我想到ObectMapper的某些readValue方法必须有类似的问题,例如接受ResolvedType而不是Class的方法。我注意到,在该类的源代码中,它在该类之前包含/unchecked/
。我不确定是否可以解决此问题,但这是有道理的。