jackson – 反序列化通用类变量

我错误地发布了这个问题。 我在这里正确地发布了这个问题……

我得到一个json字符串作为HTTP响应。 我知道它的结构。 它如下:

public class Json { public Hits hits; } public class Hits { public int found; public int start; public ArrayList<Hit> hit; } public class Hit { public String id; public Class data; } 

“data”字段可以属于任何类。 我只会在运行时知道它。 我会把它作为一个参数。 这就是我反序列化的方式。

 public  void deSerialize(Class clazz) { ObjectMapper mapper = new ObjectMapper(); mapper.readValue(jsonString, new TypeReference<Json>() {}); } 

但是我收到了一个错误 –

无法从java.lang.class访问私有java.lang.class.Class()。 无法设置访问权限。 无法使java.lang.Class构造函数可访问

如果generics类型仅动态可用,则需要显式构建JavaType

 // do NOT create new ObjectMapper per each request! final ObjectMapper mapper = new ObjectMapper(); public Json void deSerialize(Class clazz, InputStream json) { return mapper.readValue(json, mapper.getTypeFactory().constructParametricType(Json.class, clazz)); } 

示例通用反序列化接口:

 public interface Deserializable { static final ObjectMapper mapper = new ObjectMapper(); @SuppressWarnings("unchecked") default T deserialize(String rawJson) throws IOException { return mapper.readValue(rawJson, (Class) this.getClass()); } } 

您是否将Class对象序列化和反序列化为JSON? 也许在Hit中保持它为String并创建另外的启动Class.forName的getter,例如

 public class Hit { public String id; public String data; public Class getDataClass() throws Exception { return Class.forName(data); } } 

需要反序列化的JSON字符串必须包含有关参数T的类型信息。
您必须将Jackson注释放在可以作为参数T传递给类Json每个类上,以便可以通过Jackson从JSON字符串读取/写入有关参数类型T的类型信息。

让我们假设T可以是任何扩展抽象类Result类。

 public class Json { public Hits 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 { } 

一旦可以作为参数T传递的每个类(或它们的常用超类型)被注释,Jackson将在JSON中包括关于参数T信息。 然后可以在编译时不知道参数T情况下反序列化这样的JSON。
这个Jackson文档链接讨论了多态反序列化,但也可以参考这个问题。

反序列化generics类变量

我怎么告诉jackson? gson会做得更好吗?

Gson用户指南包含一个关于我理解您正在尝试完成的内容的部分,尽管该文档示例可能仍然不完整。

在博客文章中,我更详细地介绍了使用Gson 1.7.1的解决方案。 以下是相关的代码示例。

使用Jackson(1.8.2)的类似(但更多参与)解决方案也在同一博客文章中进行了演示和描述。 (不同的方法和示例使用了数百行代码,所以我在这里省略了重新发布它们。)

 public class GsonInstanceCreatorForParameterizedTypeDemo { public static void main(String[] args) { Id id1 = new Id(String.class, 42); Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create(); String json1 = gson.toJson(id1); System.out.println(json1); // actual output: {"classOfId":{},"value":42} // This contradicts what the Gson docs say happens. // With custom serialization, as described in a // previous Gson user guide section, // intended output may be // {"value":42} // input: {"value":42} String json2 = "{\"value\":42}"; Type idOfStringType=new TypeToken>(){}.getType(); Id id1Copy = gson.fromJson(json2, idOfStringType); System.out.println(id1Copy); // output: classOfId=class java.lang.String, value=42 Type idOfGsonType = new TypeToken>() {}.getType(); Id idOfGson = gson.fromJson(json2, idOfGsonType); System.out.println(idOfGson); // output: classOfId=class com.google.gson.Gson, value=42 } } class Id { private final Class classOfId; private final long value; public Id(Class classOfId, long value) { this.classOfId = classOfId; this.value = value; } @Override public String toString() { return "classOfId=" + classOfId + ", value=" + value; } } class IdInstanceCreator implements InstanceCreator> { @SuppressWarnings({ "unchecked", "rawtypes" }) public Id createInstance(Type type) { Type[] typeParameters = ((ParameterizedType) type).getActualTypeArguments(); Type idType = typeParameters[0]; return new Id((Class) idType, 0L); } }