如果我只有类的字符串名称、通过规范名称调用和对象的 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
等而且每个类都有不同的状态。我需要通用反序列化方法。
我写的是这样的:
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);
}
}
它适用于上面的汽车示例,但有一个警告强制转换异常
。
但也许有更好的方法?
哦,并不是所有的对象都会如此简单。其中一些会封装集合和其他对象。
最佳答案
问题源于编译器想要(实际上)为使用该方法的每个类型 T 创建该方法的不同实例。然而,这些论点并没有任何依据。
如果调用者不知道期望什么类,除了该类的字符串表示形式(我假设它也已保存在 JSON 中?),他将如何处理结果这个电话?因为他不知道,所以他一定只是将其用作对象,在这种情况下,该方法也可能只是返回对象。
如果调用者确实知道该类,那么他可以传入一个类作为参数,这样就不会有任何问题。
在写这篇文章时,我想到 ObectMapper 的某些 readValue 方法肯定有类似的问题,例如接受 ResolvedType 而不是 Class 的方法。我注意到,在该类的源代码中,它在类之前包含 /unchecked/
。我不确定这是否是为了解决这个问题,但这是有道理的。
关于java - 通过类名反序列化json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51934310/