Skip to content

[BUG][C++][cpp-restsdk] cpp-restsdk not able to handle maps with nested schemas ("additionalProperties") #12737

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

Open
5 tasks done
balintkissdev opened this issue Jun 29, 2022 · 1 comment

Comments

@balintkissdev
Copy link

balintkissdev commented Jun 29, 2022

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

I would like to use additionalProperties in the OpenAPI definition in order to allow accepting responses in the following JSON payload format (Array of maps with string as map key and a fixed typed object as map value. It would make my job easier if it wouldn't be in an array format, but I have to work with this type definition in a company environment. Namings are already altered to avoid sensitive info.):

[
  {
    "key property 1": {
      "id": 1,
      "name": "value 1"
    },
    "key property 2": {
      "id": 2,
      "name": "value 2"
    },
    "key property 3": {
      "id": 3,
      "name": "value 3"
    }
  }
]

image

In a generated Go client, the return type results in the following, which is the expected in Go:

// api_example.go
[]map[string]NestedSchema

However, I have to write a C++ client, and cpprest-sdk generator on the other hand generates the following type in the function signature:

// api/ExampleApi.h
pplx::task<std::vector<std::shared_ptr<std::map>>> getMapWithNestedSchema() const;

The generated ExampleApi.h and ExampleApi.cpp files do not compile, because std::map lacks the template parameters for the key and value type. Expected output is the following:

// api/ExampleApi.h
pplx::task<std::vector<std::shared_ptr<std::map<utility::string_t, std::shared_ptr<NestedSchema>>>>> getMapWithNestedSchema() const;
openapi-generator version

v6.0.0

OpenAPI declaration file content or url
swagger: '2.0'
info:
  title: Example to reproduce API generation with complex map type
  version: 0.0.0
basePath: /api/v1

schemes:
  - http
consumes:
  - application/json
produces:
  - application/json

tags:
  - name: example

paths:
  '/mapWithNestedSchema':
    get:
      operationId: 'GetMapWithNestedSchema'
      tags:
        - example
      responses:
        200:
          description: OK
          schema:
            type: 'array'
            items:
              $ref: '#/definitions/MapWithNestedSchema'
        500:
          description: Error

definitions:
  MapWithNestedSchema:
    type: 'object'
    description: 'A map with arbitrary string as key and object as value'
    additionalProperties: 
      $ref: '#/definitions/NestedSchema'
    example:
      'key property 1':
        id: 1
        name: 'value 1'
      'key property 2':
        id: 2
        name: 'value 2'
      'key property 3':
        id: 3
        name: 'value 3'
  
  NestedSchema:
    type: 'object'
    properties: 
      id:
        type: 'number'
        example: 1
      name:
        type: 'string'
        example: 'value 1'
Generation Details

generatorName: cpp-restsdk
outputDir: myclient
inputSpec: swagger.yaml

Steps to reproduce
  1. Run v6.0.0 version of openapi-codegen-cli with swagger.yml in the root folder. I used the dockerized execution.
docker run --rm -v "${PWD}:/local" --user "$(shell id -u):$(shell id -g)" openapitools/openapi-generator-cli:v6.0.0 generate \
    -i /local/swagger.yml \
    -g cpp-restsdk \
    -o /local/myclient

Also tried openapitools/openapi-generator-cli:latest too, but result was the same. Tried manually building from master with ./mvnw clean install, but the 6.0.1-SNAPSHOT build failed.

cd myclient
mkdir build
cd build
cmake ..
make
Related issues/PRs

#5148
#5222

Suggest a fix

As a workaround, I currently preprocess my swagger.yml file with sed to change the path to return "typeless items" and use them in code that way.

paths:
  '/mapWithNestedSchema':
    get:
      operationId: 'GetMapWithNestedSchema'
      tags:
        - example
      responses:
        200:
          description: OK
          schema:
            type: 'array'
            items:
              {}   # sed -i 's/$ref: '\''#\/definitions\/MapWithNestedSchema'\''/{}/g' swagger.yml 
        500:
          description: Error
// api/ExampleApi.h
pplx::task<std::vector<std::shared_ptr<Object>>> getMapWithNestedSchema() const;

swagger-codegen-cli:2.4.27 is already able to recognize an array of MapWithNestedSchema types, but has other troubles of generating MapWithNestedSchema as an std::map.

// api/ExampleApi.h
pplx::task<std::vector<std::shared_ptr<MapWithNestedSchema>>> getMapWithNestedSchema();
// models/MapWithNestedSchema.h
class  MapWithNestedSchema
    : public null<String, NestedSchema>
{
  ...
}

I tried copying the existing .mustache file templates for the API header and source and modifying them as a workaround, but so far I was only able to use the {#isMap} directive on request parameter types ({#allParams} -> {dataType}). If there would be a way to specify my custom .mustache file to check for map type or nested type in the result, that would be helpful. On the other hand, I would also appreciate help on how to improve the existing .yml file.

@balintkissdev
Copy link
Author

balintkissdev commented Jun 29, 2022

I know that removing the array generates a valid function signature with std::map<utility::string_t, std::shared_ptr<NestedSchema>>> as return type, but the YAML is given to me. I cannot change it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant