lukeautry/tsoa

Is there a way to provide example of request body?

vlad-tkachenko opened this issue · 17 comments

I see that Example annotation can be used to provide response example, but is there a way to provide an example of request inside controller?

Something like:

@Post() 
async fn(
  @Body()
  @Example<Model>({
    foo:'bar'
  }) body: Model
) { 
...
}

@lukeautry Just wondering if this is currently possible?

Yes @vlad-tkachenko and @Recodify you can. An illustration of how to use the @Example decorator can be seen here:

That link shows how to use example for response. My initial question was different - on how to provide example for request body.

Yes the @Example decorator places the example in the response section of the success code area in Swagger. I’m actually rather new to tsoa so I apologize for not knowing that. So apparently there isn’t a way to provide an example for the request body. But since most APIs respond with a structure that is the same as request body, this is the first time we have had someone ask for a way to set an example for the body.

Are you asking for someone to write an enhancement to the @Body decorator to allow for an example to be added?

If so, we can reopen this issue and mark it as [help wanted].

@dgreene1, check my original request, I'm not suggesting changing the @Body decorator, but to add support of additional extra decorator @Example specifically to provide payload example.

I will be honest, original request was opened in 2017, I'm no longer using tsoa as my library of choice for REST API development, so currently I don't need any help with that. However other users might need that functionality.

@vlad-tkachenko which library are you using? I’d love to know so we can be aware of our competition.

WoH commented

In tsoa, you can't set an exmple for the specific Request, but for the interface you use there. It looks like this:

/**
 * @example
 * {
 *   "name": "string",
 *   "array": ['one', 'two', 'three']
 * }
 */
export interface Model {
  name: string;
  array: string[];
}

Its strange to put the specific request to the model interface, if I use the same model on 2 or more APIs entry points the example will be the same.... and how to resolve @path, @query initial values?
@vlad-tkachenko I understand and I see your problem, check my PR.

@dgreene1 depends on the project: ts.ed or just typescript with vanilla express + IoC libs. To be fair, I haven't yet checked if I can provide example for payload body with ts.ed yet, so it might fail with that use case too :)

nlang commented

Just stumbled upon the same problem.

So apparently there isn’t a way to provide an example for the request body. But since most APIs respond with a structure that is the same as request body, this is the first time we have had someone ask for a way to set an example for the body.

You must be kidding, right? The most important thing when using an API is to know what to send in the body of a request. Just assuming the request body is always the same as the response body seems pretty strange to me.

Are there any plans in supporting this? I mean, it is supported by OAS3, so I think it's well worth supporting it, right?

WoH commented

You must be kidding, right? The most important thing when using an API is to know what to send in the body of a request. Just assuming the request body is always the same as the response body seems pretty strange to me.

You're misinterpreting a quote that is almost a year old as a basis for your thesis. A rather unfortunate combination to start off, especially after considering the inappropriate tone used to deliver it.

The most important thing when using an API is to know what to send in the body of a request.

One of the main reasons to use OAS is to not give 3 examples and call it documentation, but instead write a schema that allows for the API consumer to deduce viable examples themselves or sample based on the schema automatically, an approach already used by all modern tools that render OAS documents, which significantly reduces the importance of a concrete example provided by the API author.

Are there any plans in supporting this? I mean, it is supported by OAS3, so I think it's well worth supporting it, right?

Maybe use the time to read the docs instead next time and you'll find out how to already do this.

nlang commented

Sorry if I got you on the wrong foot with my comment, but I don't see how I have misinterpreted what was stated, no matter how long ago. Anyways, I don't want to argue about opinionated ways of designing or documenting APIs, just evaluating if tsoa is the right tool for us. And of course there is schema, but that can be quite complicated sometimes and an example can help to clarify things a lot. That also shouldn't be an excuse for missing functionality. And if you don't intend or have time to add it, I would also considered contributing that feature, but I didn't have any time to look into it, yet.

Reading the docs and experimenting is exactly what I did, but unfortunately it didn't help, because none of the proposed ways worked out, at least for the body. Maybe you could provide a concrete example of what should work as example for the request body? Thanks a bunch!

WoH commented

It's like any other parameter:

  /**
   * @param postComponentDto Description for the request body object
   * @example postComponentDto  {
   *   "typeId": 7010,
   *   "name": "BTP-CLOSURE-4-NE",
   *   "description": "Gf-AP (max. 4 utilisation units)",
   *   "cost": 140.50,
   *   "data": {}
   * }
   * @example postComponentDto  {
   *   "typeId": 3010,
   *   "name": "SPLITTER-8",
   *   "description": "SPLITTER 1:8",
   *   "cost": 200,
   *   "data": {
   *     "splittingRatio": 8
   *   }
   * }
   */
  @Post('/components')
  public async postComponent(
    // ...
    @Body() postComponentDto: PostComponentDto
  ) //...
nlang commented

Thanks! I already tried exactly that, but it didn’t get rendered. I will try again and let you know if I did get it to work. Thanks again!

WoH commented

Did you use JSON (with quotes around the keys)? That may have been the issue. If that doesn't work, feel free to open an issue.

nlang commented

@WoH thanks for your help, that did the trick. I also thought that you have to specify the type name of the parameter as in the @Example<>() annotation, but you have to use the parameter name here!

Just in case I missed that: There is no way to use the @Example<>() annotation for the request body? That would be way better, because you get type checking that helps to keep docs reflecting what is really implemented, especially on changes.

Use @param Interface for this. In example:

interface Human{
    first_name: string;
    last_name: string;
}

/**
 * @param Human human details
 */