包含泛型类型对象的java jackson解析对象
我有以下问题 我必须将json请求解析为包含泛型类型字段的对象 编辑 我已经使用常规类类型进行了一些测试(因此,在用泛型替换它之前,我会让它工作)。现在,对单个元素进行解析非常有效 问题是当我需要从该类中解析出一个列表对象时 所以我不得不告诉jackson,我的T是list类型,而不仅仅是AlbumModel 这是我试过的包含泛型类型对象的java jackson解析对象,java,json,parsing,generics,jackson,Java,Json,Parsing,Generics,Jackson,我有以下问题 我必须将json请求解析为包含泛型类型字段的对象 编辑 我已经使用常规类类型进行了一些测试(因此,在用泛型替换它之前,我会让它工作)。现在,对单个元素进行解析非常有效 问题是当我需要从该类中解析出一个列表对象时 所以我不得不告诉jackson,我的T是list类型,而不仅仅是AlbumModel 这是我试过的 @Override public ListResponseModel<AlbumModel> parse(String responseBody) th
@Override
public ListResponseModel<AlbumModel> parse(String responseBody) throws Exception {
JavaType type = mapper.getTypeFactory().constructParametricType(ResponseModel.class,
AlbumModel.class);
return mapper.readValue(responseBody,
mapper.getTypeFactory().constructParametricType(ResponseModel.class, type));
}
@覆盖
公共ListResponseModel解析(字符串ResponseBy)引发异常{
JavaType type=mapper.getTypeFactory().ConstructParameterType(ResponseModel.class,
模型类);
返回mapper.readValue(responseBody,
getTypeFactory().ConstructParameterType(ResponseModel.class,type));
}
但是上面的代码不起作用。这样的问题有什么解决方案
我在ListResponseModel中的泛型类型定义如下:List data
例如:
public class BaseResponseModel<T> {
@JsonProperty("data")
private T data;
@JsonProperty("paginations")
private PaginationModel pagination;
}
公共类BaseResponseModel{
@JsonProperty(“数据”)
私有T数据;
@JsonProperty(“分页”)
私有分页模型分页;
}
到目前为止,我有以下代码,但它总是解析成散列
public class ResponseParser extends BaseJacksonMapperResponseParser<ResponseModel<AlbumModel>> {
public static final String TAG = ResponseParser.class.getSimpleName();
@Override
public ResponseModel<AlbumModel> parse(String responseBody) throws Exception {
return mapper.readValue(responseBody,
mapper.getTypeFactory().constructParametricType(ResponseModel.class, AlbumModel.class));
}
}
public abstract class BaseJacksonMapperResponseParser<T> implements HttpResponseParser<T> {
public static final String TAG = BaseJacksonMapperResponseParser.class.getSimpleName();
public static ObjectMapper mapper = new ObjectMapper();
static {
mapper.disable(Feature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.enable(Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
}
}
公共类响应器扩展BaseJacksonApperResponser{
公共静态最终字符串标记=ResponseParser.class.getSimpleName();
@凌驾
公共响应模型解析(字符串响应库)引发异常{
返回mapper.readValue(responseBody,
getTypeFactory().ConstructParameterType(ResponseModel.class,AlbumModel.class));
}
}
公共抽象类BaseJacksonApperResponse瑟实现了HttpResponseParser{
public static final String TAG=basejacksonapperresponseparser.class.getSimpleName();
public static ObjectMapper mapper=new ObjectMapper();
静止的{
mapper.disable(未知属性上的Feature.FAIL);
mapper.enable(Feature.ACCEPT\u EMPTY\u STRING\u作为\u NULL\u对象);
configure(SerializationConfig.Feature.WRAP\u ROOT\u值,true);
}
}
由于您正在使用Jackson,您可能需要创建一个自定义JsonDeserializer或JsonSerializer,具体取决于您是在处理响应还是请求。我用日期来做这件事,因为在我的回复中,我想要一个标准的视图。我不是100%肯定它会与通用领域,虽然。下面是我正在做的一个例子:
public class DateSerializer extends JsonSerializer<Date> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZ");
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
String dateString = dateFormat.format(value);
jgen.writeString(dateString);
}
}
您的T类型将在运行时被“擦除”,因此Jackson不知道T的真实类型,并将其反序列化为映射。解析方法需要第二个参数,它将是classclazz
或TypeReference
或java.lang.reflect.Type
编辑
关于TypeReference魔力的小解释。当您执行new XX(){}时,您正在创建一个匿名类,因此如果它是一个带有typevariables(如果您愿意,可以参数化)的类,那么newX(){},
您将能够在运行时以java类型检索List
。这与您所做的非常相似:
abstract class MyGenericClass<T> {}
class MySpecializedClass extends MyGenericClass<List<Y>> {}
抽象类MyGenericClass{}
类MySpecializedClass扩展MyGenericClass{}
我同意尤金的回答,但我只想再详细说明一下。第一步是重构您的解析方法,以便它接受第二个参数。您需要调用方传入一个TypeReference实例,而不是在方法中分配类型引用
public BaseResponseModel<T> parse(String responseBody, TypeReference<T> ref) throws Exception {
return mapper.readValue(responseBody, ref);
}
public BaseResponseModel解析(字符串responseBody,TypeReference)引发异常{
返回mapper.readValue(responseBody,ref);
}
不幸的是,您的代码片段没有显示调用parse的代码-因此我将补充一些内容:
BaseResponseParser<Collection<Person>> parser = new BaseResponseParser<Collection<Person>>();
BaseResponseModel<Collection<Person>> result = parser.parse(jsonText, new TypeReference<Collection<Person>>(){});
BaseResponseParser=新的BaseResponseParser();
BaseResponseModel result=parser.parse(jsonText,new TypeReference(){});
请注意,在本例中编译TypeReference实例时,它是对我们期望的实际具体类的类型引用
您可以在运行时做同样的事情传入类,但是TypeReference功能更强大,因为它甚至可以在类型T是泛型集合时工作。TypeReference实现中有一种魔力,它允许保留通常会被擦除的类型信息
[更新]
更新为使用
集合
。注意-据我所知,列表应该也能工作,但我仔细检查了一个项目,在这个项目中我使用了jackson来反序列化集合。基类收藏确实奏效了,所以我坚持了下来。好的,我开始买这个了。。我使用一个对象完成了这项工作,但我无法为列表完成这项工作。你能在这方面提供更多的信息吗?谢谢你迄今为止的努力。好的,我已经成功了。与此类似,但你证明了一点。谢谢。我唯一讨厌的是,我必须发送.class,还要定义泛型参数,最后我得到了一个类似于新解析器(AlbumModel.class)的东西
BaseResponseParser<Collection<Person>> parser = new BaseResponseParser<Collection<Person>>();
BaseResponseModel<Collection<Person>> result = parser.parse(jsonText, new TypeReference<Collection<Person>>(){});