Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
包含泛型类型对象的java jackson解析对象_Java_Json_Parsing_Generics_Jackson - Fatal编程技术网

包含泛型类型对象的java jackson解析对象

包含泛型类型对象的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

我有以下问题

我必须将json请求解析为包含泛型类型字段的对象

编辑

我已经使用常规类类型进行了一些测试(因此,在用泛型替换它之前,我会让它工作)。现在,对单个元素进行解析非常有效

问题是当我需要从该类中解析出一个列表对象时

所以我不得不告诉jackson,我的T是list类型,而不仅仅是AlbumModel

这是我试过的

 @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(如果您愿意,可以参数化)的类,那么new
X(){},
您将能够在运行时以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>>(){});