-
Notifications
You must be signed in to change notification settings - Fork 901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide a way to automatically deserialize non-OK JSON response using WebClient
and RestClient
#4382
Comments
Hi @ikhoon, I understand the intent of this issue is to deserialize error response for the tests. |
The response format between a normal response and an error response may be different in most cases.
We need to update the error message below. If a
|
For gentle error messages, we can internally create class HttpStatusPredicate<T> extends Predicate<T> {
// Use the following fields to generate error messages
@Nullable
private HttpStatus status;
@Nullable
private HttpStatusClass statusClass;
...
}
// WebClientRequestPreparation
public <T> ... asJson(Class<? extends T> clazz, HttpStatus status) {
return asJson(clazz, new HttpStatusPredicate(status));
}
public <T> ... asJson(Class<? extends T> clazz, Predicate<HttpStatus> predicate) {
...
} |
Thanks a lot🙇 The part I was wondering about has been solved. |
Hi @ikhoon! I'm trying to this issue. |
We can implement final class HttpStatusPredicate extends Predicate<HttpStatus> {
@Nullable
private HttpStatus status;
@Nullable
private HttpStatusClass statusClass;
...
@Override
boolean test(HttpStatus status) {
if (this.status != null) {
return this.status.equals(status);
}
assert statusClass != null;
return status.codeClass() == statusClass;
}
@Nullable
HttpStatus status() {
return status;
}
@Nullable
HttpStatusClass statusClass() {
return statusClass;
}
} The custom // In AggregatedResponseAs
private static final HttpStatusPredicate SUCCESS_PREDICATE = new HttpStatusPredicate(HttpStatusClass.SUCCESS);
private static <T> ResponseEntity<T>
newJsonResponseEntity(AggregatedHttpResponse response,
JsonDecoder<T> decoder) {
return newJsonResponseEntity(response, decoder, SUCCESS_PREDICATE);
}
private static <T> ResponseEntity<T>
newJsonResponseEntity(AggregatedHttpResponse response,
JsonDecoder<T> decoder, HttpStatus status) {
return newJsonResponseEntity(response, decoder, new HttpStatusPredicate(status));
}
private static <T> ResponseEntity<T>
newJsonResponseEntity(AggregatedHttpResponse response,
JsonDecoder<T> decoder, Predicate<HttpStatus> status) {
if (status instanceof HttpStatusPredicate) {
... // Extract either HttpStatus or HttpStatusClass to provide the expected status.
}
} |
Thanks for the pull request. I will take a look at it soon. |
Motivation: Please refer to #4382 Modifications: - Add some methods to specify what type of response is allowed - Add `HttpStatusPredicate` and `HttpStatusClassPredicate` class to deserialize non-OK JSON response for more shortcut methods. Result: - Closes #4382 - Users can deserialize non-OK JSON response like the following ```java // WebClient WebClient.of().prepare() .as(ResponseAs.blocking() .andThen(res -> "Unexpected server error", res -> res.status().isServerError()) .andThen(res -> "missing header", res -> !res.headers().contains("x-header")) .orElse(AggregatedHttpObject::contentUtf8)) .execute(); // RestClient final ResponseEntity<MyResponse> res = RestClient.of(server.httpUri()).get("/") .execute(ResponseAs.blocking() .<MyResponse>andThenJson(MyError.class, res -> res.status().isClientError()) .andThenJson(EmptyMessage.class, res -> res.status().isInformational()) .orElseJson(MyMessage.class)); ``` --------- Co-authored-by: jrhee17 <[email protected]> Co-authored-by: Hannam Rhee <[email protected]> Co-authored-by: minu <[email protected]> Co-authored-by: minwoox <[email protected]>
…#5002) Motivation: Please refer to line#4382 Modifications: - Add some methods to specify what type of response is allowed - Add `HttpStatusPredicate` and `HttpStatusClassPredicate` class to deserialize non-OK JSON response for more shortcut methods. Result: - Closes line#4382 - Users can deserialize non-OK JSON response like the following ```java // WebClient WebClient.of().prepare() .as(ResponseAs.blocking() .andThen(res -> "Unexpected server error", res -> res.status().isServerError()) .andThen(res -> "missing header", res -> !res.headers().contains("x-header")) .orElse(AggregatedHttpObject::contentUtf8)) .execute(); // RestClient final ResponseEntity<MyResponse> res = RestClient.of(server.httpUri()).get("/") .execute(ResponseAs.blocking() .<MyResponse>andThenJson(MyError.class, res -> res.status().isClientError()) .andThenJson(EmptyMessage.class, res -> res.status().isInformational()) .orElseJson(MyMessage.class)); ``` --------- Co-authored-by: jrhee17 <[email protected]> Co-authored-by: Hannam Rhee <[email protected]> Co-authored-by: minu <[email protected]> Co-authored-by: minwoox <[email protected]>
WebClient
orRestClient
is able to deserialize a JSON response into an object using:The client tries to convert the JSON response into an object when the class of response status is a success.
armeria/core/src/main/java/com/linecorp/armeria/client/AggregatedResponseAs.java
Lines 58 to 62 in ccf630c
I believe that most REST clients expect a 2xx status for normal situations.
However, when it comes to tests, it would be inconvenient. Users might want to test an error response.
So it could be useful to add some variant methods of
.asJson(...)
ofWebClient
and.execute(...)
ofRestClient
In addition to
HttpStatus
, we can also addPredicate<HttpStatus>
andHttpStatusClass
as a parameter.The text was updated successfully, but these errors were encountered: