我有一个json字符串,我应该反序列化到下面的类

class Data <T> {
    int found;
    Class<T> hits
}

我该怎么做? 这是通常的做法

mapper.readValue(jsonString, Data.class);

但是我怎么提到T代表什么呢?


当前回答

您需要为所使用的每个泛型类型创建一个TypeReference对象,并使用该对象进行反序列化。例如:

mapper.readValue(jsonString, new TypeReference<Data<String>>() {});

其他回答

你不能这样做:你必须指定完全解析的类型,比如Data<MyType>。T只是一个变量,as没有意义。

但如果您的意思是T将是已知的,只是不是静态的,那么您需要动态地创建与TypeReference等价的TypeReference。其他问题可能已经提到了这一点,但它应该是这样的:

public Data<T> read(InputStream json, Class<T> contentClass) {
   JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, contentClass);
   return mapper.readValue(json, type);
}

您需要为所使用的每个泛型类型创建一个TypeReference对象,并使用该对象进行反序列化。例如:

mapper.readValue(jsonString, new TypeReference<Data<String>>() {});

如果你正在使用scala,并且在编译时知道泛型类型,但不想在所有api层中手动传递TypeReference,你可以使用以下代码(使用jackson 2.9.5):

def read[T](entityStream: InputStream)(implicit typeTag: WeakTypeTag[T]): T = {

    //nathang: all of this *crazy* scala reflection allows us to handle List[Seq[Map[Int,Value]]]] without passing
    // new TypeReference[List[Seq[Map[Int,Value]]]]](){} to the function

    def recursiveFindGenericClasses(t: Type): JavaType = {
      val current = typeTag.mirror.runtimeClass(t)

      if (t.typeArgs.isEmpty) {
        val noSubtypes = Seq.empty[Class[_]]
        factory.constructParametricType(current, noSubtypes:_*)
      }

      else {
        val genericSubtypes: Seq[JavaType] = t.typeArgs.map(recursiveFindGenericClasses)
        factory.constructParametricType(current, genericSubtypes:_*)
      }

    }

    val javaType = recursiveFindGenericClasses(typeTag.tpe)

    json.readValue[T](entityStream, javaType)
  }

可以这样使用:

read[List[Map[Int, SomethingToSerialize]]](inputStream)

你可以把它包装在另一个类中,这个类知道你的泛型类型的类型。

Eg,

class Wrapper {
 private Data<Something> data;
}
mapper.readValue(jsonString, Wrapper.class);

这里Something是一个具体的类型。每个具体化类型都需要一个包装器。否则Jackson就不知道该创建什么对象。

public class Data<T> extends JsonDeserializer implements ContextualDeserializer {
    private Class<T> cls;
    public JsonDeserializer createContextual(DeserializationContext ctx, BeanProperty prop) throws JsonMappingException {
        cls = (Class<T>) ctx.getContextualType().getRawClass();
        return this;
    }
    ...
 }