有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

自定义Jackson反序列化程序中的java委托

情况如下:我已经设法让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的值将不是一个对象,而是一个String。我需要捕获异常并将该值分配给ResponseData中的另一个属性,例如String errorMessage。我的想法是用@JsonDeserialize( using = ResponseDeserializer.class )注释response属性,但我不知道如何正确地实现JsonDeserializer,以便它将反序列化委托给Jackson的实现,并在异常发生时捕获异常

关于更多的上下文,我使用WebClient作为HTTP客户机,并使用进行反序列化的交换Function<ClientResponse, Mono<ResponseWrapper<T>>处理响应


共 (1) 个答案

  1. # 1 楼答案

    为了获得泛型类型,我有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 );
               
           }
    
       }
       
    }