OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.32k stars 6.45k forks source link

[C++][Pistache-server] Object in a query generates code that do not compile #1298

Open CyrilleBenard opened 5 years ago

CyrilleBenard commented 5 years ago
Description

If a query owns an object in a parameter, the generator makes code that do not compile. It seems that the corresponding method is not generated.

The compilation error looks like :

g++ -c  -I./api -I./model -I./impl -Wall -g -std=c++11 -o obj/api/CheckApi.o api/CheckApi.cpp
api/CheckApi.cpp: In member function ‘void com::bcom::amf::microservice::server::ms1::api::CheckApi::list_handler(const Pistache::Rest::Request&, Pistache::Http::ResponseWriter)’:
api/CheckApi.cpp:51:55: error: no matching function for call to ‘fromStringValue(std::__cxx11::basic_string<char>, com::bcom::amf::microservice::server::ms1::model::PresenceState&)’
         if(fromStringValue(infoClassQuery.get(), value)){
                                                       ^
In file included from api/CheckApi.cpp:14:0:
./model/Helpers.h:39:10: note: candidate: bool org::openapitools::server::helpers::fromStringValue(const string&, std::__cxx11::string&)
     bool fromStringValue(const std::string &inStr, std::string &value);

... etc
openapi-generator version

Current master : 3.3.2-SNAPSHOT

OpenAPI declaration file content or url
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Check generation of a structured object in the query (Pistache)
  description: Internal ref filename is check_object_in_query.yaml

servers:
  - url: http://localhost:8080
paths:
  /Check:
    get:
      summary: Check object in the query
      operationId: list
      tags:
        - Check
      parameters:
        - name: info-class
          in: query
          description: UE Context Information Class
          schema:
            $ref: '#/components/schemas/PresenceState'

      responses:
        '200':
          description: Everythings gonna be alright
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:    
              schema:
                type: string
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                type: string

components:
  schemas:

    PresenceState:
      type: object
      properties:
        prop1:
          type: string
Command line used for generation

Generate :

openapi-generator-cli.sh generate -i ./openapi.yaml -g cpp-pistache-server -c ./config.json -o .

Compile :

g++ -c  -I./api -I./model -I./impl -Wall -g -std=c++11 -o obj/api/CheckApi.o api/CheckApi.cpp
Steps to reproduce

Generate & compile

Related issues/PRs

N/A

Suggest a fix/enhancement

Each property of the query object should be considered separately, one by one, and for each of them, call the fromStringValue method to assign the corresponding member of the instantiated model.

Or

The model should implement its own 'fromStringValue" method that will assign all the values of its members from the query string.

Second suggestion is probably much more elegant. I don't know how it is solved in others languages but I trust in @etherealjoy or @stkrwork to make the best choice :eyeglasses:

etherealjoy commented 5 years ago

@CyrilleBenard How do you pass Object in Query? Is this valid? :)

EDIT: I see it is there in OAS3

Objects can be serialized as:
form – /points?color=R,100,G,200,B,150 or /points?R=100&G=200&B=150, 
depending on the explode keyword
deepObject – /points?color[R]=100&color[G]=200&color[B]=150

I am wondering how we could even do this with nested objects :|

CyrilleBenard commented 5 years ago

It seems that it is already done for jaxrs-resteasy generator, for example. I mean the generated code does not fail with my example shown.

The spec says that we have to use content (application/json) for complex parameter in the query, so that we may understand that nested objects may not be defined outside this rule (?)

By default, could you make a fix to, at least, consider a simple case like the one I showed ? No nested / complex objects, and just to make the generator producing C++ code that do compile, even if it is not perfect ?

CyrilleBenard commented 5 years ago

I want to add that it is not specific to an object inside a query but to the use of a model. For example, if I set this schema :

PresenceState2:
      type: string
      enum: 
        - "First enum value"

And replace the use of

$ref: '#/components/schemas/PresenceState' 

by

$ref: '#/components/schemas/PresenceState2'

The same kind of code is generated :

void CheckApi::list_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
    // Getting the query params
    auto infoClassQuery = request.query().get("info-class");
    Pistache::Optional<PresenceState2> infoClass;
    if(!infoClassQuery.isEmpty()){
        PresenceState2 value;
        if(fromStringValue(infoClassQuery.get(), value)){
            infoClass = Pistache::Some(value);
        }
    }

    try {
      this->list(infoClass, response);
    } catch (std::runtime_error & e) {
      //send a 400 error
      response.send(Pistache::Http::Code::Bad_Request, e.what());
      return;
    }
}

fromStringValue is called with its second argument of type PresenceState2 that is unknown for it :/

etherealjoy commented 5 years ago

@CyrilleBenard For now pistache supports only basic query parameters i.e. primitives.

CyrilleBenard commented 5 years ago

May be I missed something (?) but why do you say it is a Pistache limitation ? Except the call to Pistache::Some(value); (we could avoid), the serialization is non dependent of Pistache.

The serialization may be some successive calls to fromStringValue for each query parameter and the result would be set to each Model member variable, isn't it ?

This is a simple view, I must admit, but it's just to explain my point of view and trying to understand what's blocking.

etherealjoy commented 5 years ago

It is not a pistache limitation. some additional things needs to be done in the mustache files of the pistache generator.

CyrilleBenard commented 5 years ago

Ah OK, that sounds great. So, I misunderstood what you said before. Thank you for your answer :+1:

jnar331 commented 2 months ago

any news on this issue?