armeria icon indicating copy to clipboard operation
armeria copied to clipboard

Provide a way to send a JSON object with `WebClient`

Open ikhoon opened this issue 4 years ago • 10 comments

JSON is the dominant exchange format for REST API. However, Armeria's WebClient does not provide any JSON-specific APIs. I believe it should be useful additions if we provide:

WebClient client = WebClient.of();
// Send a serialized JSON object with "applicaiton/json"
HttpResponse response = client.postJson("/items", new MyItem()); 
HttpResponse response = client.putJson("/items", new MyItem());
HttpResponse response = client.patchJson("/items", new MyItem());

HttpResponse response = client.prepare()
                              .post("/items")
                              .contentJson(new MyItem())
                              .execute();

ikhoon avatar Jul 19 '21 03:07 ikhoon

~~Additionally, how do you think similar feature, HttpRequest.ofJson?~~ Additionally, how about adding HttpRequest.ofJson also?

0x1306e6d avatar Jul 19 '21 06:07 0x1306e6d

+1 to having HttpRequest.ofJson() as well.

trustin avatar Jul 19 '21 07:07 trustin

It would also be nice to have APIs that automatically convert a response into an object.

  • Content-Type
    • We can support well-known media types such as:
      • "application/json"
      • "application/protobuf" (We can add this later cause Protobuf is not a popular format for REST.)
    • An UnsupportedMediaTypeException could complete the returned future for unknown media types.
    • An JsonProcessingException could complete the returned future when failing to decode a JSON in response body into an object.
  • Status
    • The default expected HTTP response is 200 OK. If another status is received;
    • UnexpectedHttpStatusException could complete the returned future.
    • Alternatively, an additional API that can specify an expected HTTP status.
interface HttpResponse {
  <T> CompletableFuture<T> aggregateAs(Class<? extends T> clazz);
  <T> CompletableFuture<T> aggregateAs(HttpStatus expectedStatus, Class<? extends T> clazz);
  <T> CompletableFuture<T> aggregateAs(HttpStatus expectedStatus, Class<? extends T> clazz, EventExecutor executor);
}

ikhoon avatar Jul 20 '21 06:07 ikhoon

I'm interested in this!

karellen-kim avatar Jul 20 '21 11:07 karellen-kim

Thanks! It's all yours.

ikhoon avatar Jul 20 '21 11:07 ikhoon

@ikhoon @trustin @minwoox @jrhee17 Hi, Armeria team. Could you consider to assign this issue to me? I'd like to start a contribution with this issue. Thank you!

monorisk avatar Oct 15 '24 15:10 monorisk

Sure, I think this PR still has value in:

  • Adding convenience methods to send a JSON directly via WebClient
WebClient client;
HttpResponse response = client.postJson("/items", new MyItem()); 
HttpResponse response = client.putJson("/items", new MyItem());
HttpResponse response = client.patchJson("/items", new MyItem());
  • Adding a factory method HttpRequest.ofJson to create a request with a JSON
HttpRequest.ofJson(obj);

cc. @ikhoon the original proposer of the issue

jrhee17 avatar Oct 16 '24 01:10 jrhee17

On second thought, returning a ResponseEntity<T> would be better for JSON exchanges. I propose the following API style:

CompletableFuture<ResponseEntity<Result>> response = client.postJson<Result>("/items", new MyItem()); 

ikhoon avatar Oct 16 '24 08:10 ikhoon

@jrhee17 @ikhoon Thank you for your opinions, jrh2217 & ikhoon. I have questions on those things.

Q1. What is a default content type & charset of the json method?

I've checked other methods on the WebClient and guess that the default charset is the UTF-8 & the default content-type is application/json, right?

Q2. Which arguments are required on the new json method?

Some methods on the WebClient have more arguments than path & content object. (ex: query params, request headers)

Do you think that the methods only need the path & content object?

Q3. Result of the json method.

Is there any convention on the WebClient? I think there is no method that returns the CompletableFuture<ResponseEntity<T>>. I'll choose the return type that ikhoon mentioned if there is no convention or it's more helpful to users.


Please give me your opinions~! Thank you~! 🙇‍♂️

monorisk avatar Oct 16 '24 14:10 monorisk

guess that the default charset is the UTF-8 & the default content-type is application/json, right?

Yes

Do you think that the methods only need the path & content object?

I think just a path/content is fine for starters

I'll choose the return type that ikhoon mentioned

Sounds good to me

jrhee17 avatar Oct 17 '24 02:10 jrhee17