Десериализация WebClient

В своем приложении я делаю запросы к vk.com. Я использую spring 5 и webclient. Вот мой код:

private <R extends JsonMarker,
        E extends RuntimeException> Mono<R> parseResponseToSingleObject(
        final ClientResponse response,
        final Class<R> responseClass,
        final Class<E> errorClass) {
    return Mono.fromCallable(
            () -> {
                val json = response
                        .bodyToMono(ByteArrayResource.class)
                        .map(ByteArrayResource::getByteArray)
                        .map(String::new)
                        .block();
                System.out.println(json);
                return json;
            })
            .subscribeOn(blockExec)
            .flatMap(json -> {
                if (isRespBody(json)) {
                    return Mono.fromCallable(
                            (Callable<SingleObject<R>>) () ->
                                    jsonMapper.readValue(
                                            json,
                                            typeFactory.constructParametricType(SINGLE_OBJECT_CLASS, responseClass)
                                    ))
                            .subscribeOn(blockExec)
                            .flatMap(body -> body.getResponse() != null
                                    ? Mono.just(body.getResponse())
                                    : Mono.empty());
                } else {
                    if (isErrorBody(json)) {
                        return fromCallable(
                                (Callable<SingleError<E>>) () ->
                                        jsonMapper.readValue(
                                                json, 
                                                typeFactory.constructParametricType(SINGLE_ERROR_CLASS, errorClass)))
                                .subscribeOn(blockExec)
                                .flatMap(body -> Mono.error(body.getError()));
                    } else return Mono.error(InvalidJsonException::new);
                }
            });
}

Также я создал pojo классы:

// аннотации lombok
@JsonIgnoreProperties(ignoreUnknown = true)
public class SingleObject<R extends JsonMarker> {

    @JsonProperty(value = "response")
    private R response;
}

// аннотации lombok
@JsonIgnoreProperties(ignoreUnknown = true)
public class SingleError<R extends RuntimeException> {

    @JsonProperty(value = "error")
    private R error;
}

// аннотации lombok
@JsonIgnoreProperties(ignoreUnknown = true)
public class ApiException extends RuntimeException {

    @JsonProperty(value = "error_code")
    private int code;

    @JsonProperty(value = "error_msg")
    private String message;

    @JsonProperty(value = "method")
    private String method;
}

// аннотации lombok
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserJson implements JsonMarker {

    @JsonProperty(value = "id")
    private Integer ID;

    @JsonProperty(value = "first_name")
    private String firstName;

    @JsonProperty(value = "last_name")
    private String lastName;

    @JsonProperty(value = "is_closed")
    private boolean closed;

    @JsonProperty(value = "deactivated")
    private String deactivated;

    @JsonProperty(value = "sex")
    private int sex;
}

Мне нужно, чтобы метод parseResponseToSingleObject возвращал объект либо бросал исключение ApiException. Поэтому я сперва преобразовываю ответ в String, а потом, в зависимости от начала строки, начинаю десериализовывать. Это решение работает корректно, но мне кажется это ужасный код. Мне бы хотелось сразу парсить ответ в объект, без преобразования в String. К тому же, тут 3 блокирующих вызова, а эти методы я вызываю из контроллера. Я обошел блокировку через scheduler, но мне кажется так делать нежелательно.

Я только начинаю изучать reactive стек и хочу знать как мне сделать это правильно.


Ответы (0 шт):