问题描述
情况如下:我设法让 Jackson 反序列化以下泛型 ResponseWrapper<T>
。
static final class ResponseWrapper<T> {
private ResponseData <T> response;
protected static final class ResponseData<T> {
private int status;
private T data;
}
}
使用以下 ParameterizedTypeReference
public static <T> ParameterizedTypeReference <ResponseWrapper<T>> typeReferenceOf ( Class<T> tClass ) {
return ParameterizedTypeReference.forType( ParameterizedTypeImpl.make( ResponseWrapper.class,new Type[]{ tClass },null ) );
}
问题:我需要处理 T
的反序列化将失败的情况,因为 data
的值不是一个对象而是一个 {{1} } 反而。我需要捕获异常并将此值分配给 String
中的另一个属性,例如 ResponseData
。我的看法是用 String errorMessage
注释 response
属性,但我不知道如何正确实现 @JsonDeserialize( using = ResponseDeserializer.class )
以便它将反序列化委托给 Jackson 的实现,我只是捕获发生时异常。
有关更多上下文,我使用 JsonDeserializer
作为 HTTP 客户端,并使用发生反序列化的交换 WebClient
处理响应。
解决方法
为了获得泛型类型,我让 ResponseDeserializer
实现 ContextualDeserializer
@Override
public JsonDeserializer<?> createContextual ( DeserializationContext context,BeanProperty property ) throws JsonMappingException {
JavaType wrapperType = property.getType();
JavaType valueType = wrapperType.containedType(0);
return new ResponseDeserializer<>( valueType );
}
这使我能够使用特定的 JavaType
创建反序列化器的具体实例。以下是完整的解决方案:
private static final class ResponseDeserializer<T> extends JsonObjectDeserializer<ResponseWrapper.ResponseData<T>> implements ContextualDeserializer {
private final JavaType javaType;
public ResponseDeserializer ( ) {
this.javaType = null;
}
public ResponseDeserializer ( JavaType javaType ) {
this.javaType = javaType;
}
@Override
public JsonDeserializer<?> createContextual ( DeserializationContext context,BeanProperty property ) throws JsonMappingException {
JavaType wrapperType = property.getType();
JavaType valueType = wrapperType.containedType(0);
return new ResponseDeserializer<>( valueType );
}
@Override
protected ResponseWrapper.ResponseData<T> deserializeObject ( JsonParser jsonParser,DeserializationContext context,ObjectCodec codec,JsonNode tree ) throws IOException {
int status = tree.get( "status" ).asInt();
JsonNode dataNode = tree.get( "data" );
try {
final T data; {
if ( dataNode == null ) {
data = null;
} else {
JsonParser dataParser = dataNode.traverse();
JsonToken token = dataParser.nextToken(); // handle?
data = context.readValue( dataParser,javaType );
}
};
return new ResponseWrapper.ResponseData<T>( status,data );
} catch ( InvalidDefinitionException e ) {
String errorMessage = dataNode.asText();
return new ResponseWrapper.ResponseData<T>( status,errorMessage );
}
}
}