30

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

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

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;
}

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

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

但我收到一个错误 -

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

4

6 回答 6

33

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

// 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));
}
于 2012-07-27T19:27:44.637 回答
9

示例通用反序列化接口:

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());
    }
}
于 2016-01-20T13:06:35.227 回答
2

您正在将 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);
    }
}
于 2012-07-26T12:22:25.887 回答
1

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

让我们假设它T可以是任何扩展抽象类的类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 {

}

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

于 2018-02-20T08:01:10.057 回答
0

对我来说,这样的事情适用于类似的情况

public <T> T jsonToObject(String jsonContainsObject, Class<T> objectType) {
       ObjectMapper objectMapper = new ObjectMapper();
       try {
         return objectMapper.readValue(jsonContainsObject, objectType);
       } catch (JsonProcessingException e) {
         //Your exception handling
       }
    return null; 
}
于 2022-01-31T11:44:53.243 回答
-1

反序列化通用类变量

...

我怎么告诉杰克逊?gson会做得更好吗?

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

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

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

public class GsonInstanceCreatorForParameterizedTypeDemo  
{  
 public static void main(String[] args)  
 {  
  Id<String> id1 = new Id<String>(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<Id<String>>(){}.getType();  
  Id<String> id1Copy = gson.fromJson(json2, idOfStringType);  
  System.out.println(id1Copy);  
  // output: classOfId=class java.lang.String, value=42  
  
  Type idOfGsonType = new TypeToken<Id<Gson>>() {}.getType();  
  Id<Gson> idOfGson = gson.fromJson(json2, idOfGsonType);  
  System.out.println(idOfGson);  
  // output: classOfId=class com.google.gson.Gson, value=42  
 }  
}  
  
class Id<T>  
{  
 private final Class<T> classOfId;  
 private final long value;  
  
 public Id(Class<T> classOfId, long value)  
 {  
  this.classOfId = classOfId;  
  this.value = value;  
 }  
  
 @Override  
 public String toString()  
 {  
  return "classOfId=" + classOfId + ", value=" + value;  
 }  
}  
  
class IdInstanceCreator implements InstanceCreator<Id<?>>  
{  
 @SuppressWarnings({ "unchecked", "rawtypes" })  
 public Id<?> createInstance(Type type)  
 {  
  Type[] typeParameters =   
    ((ParameterizedType) type).getActualTypeArguments();  
  Type idType = typeParameters[0];  
  return new Id((Class<?>) idType, 0L);  
 }  
} 
于 2012-07-26T16:26:49.460 回答