dankinsoid / VaporToOpenAPI

OpenAPI specification generator for Vapor based Swift projects.
MIT License
98 stars 8 forks source link

Incorrect behavior when using ContentConfiguration and .convertToSnakeCase #21

Closed LukisMaster closed 5 months ago

LukisMaster commented 5 months ago

Hello! In our service, we utilize custom settings in the configuration file, as this rule is maintained throughout the entire project across all services. This concerns the usage of snake_case in all JSON parameter names.

Снимок экрана 2024-04-01 в 19 18 11

Unfortunately, this leads to incorrect behavior of your package, resulting in an incorrectly generated swagger.json file. In some places, the names of the models are also written in snake_case, while in other places, they are written according to the structure name.

Screenshots of the code and the swagger UI are attached for reference.

Снимок экрана 2024-04-01 в 19 15 19

Снимок экрана 2024-04-01 в 19 37 36

Снимок экрана 2024-04-01 в 19 21 19

Снимок экрана 2024-04-01 в 19 20 34

dankinsoid commented 5 months ago

@LukisMaster I'm not sure that it's possible to reuse the content encoder configurations, but you can set global var KeyEncodingStrategy.default

import SwiftOpenAPI

KeyEncodingStrategy.default = .convertToSnakeCase
dankinsoid commented 5 months ago

Also you can customize a specific schema by using .scheme func instead of .type:

body: .schema(.decode(CreateDepartmentHttpRequest.self, keyEncodingStrategy: .convertToSnakeCase))
dankinsoid commented 5 months ago

and DateEncodingFormat.default is also configurable

LukisMaster commented 5 months ago
KeyEncodingStrategy.default = .convertToSnakeCase

I added this code to the application configuration file, but it had no effect. I think the problem is that the global json encode conversion settings (see below) they also affect the final output of swagger.json.

    let encoder = JSONEncoder()
    encoder.keyEncodingStrategy = .convertToSnakeCase
    encoder.dateEncodingStrategy = .iso8601
    ContentConfiguration.global.use(encoder: encoder, for: .json)

    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    decoder.dateDecodingStrategy = .iso8601
    ContentConfiguration.global.use(decoder: decoder, for: .json)

And this does not interfere in any way, except for the section with schemas. This can be seen in the screenshot below. and here it is necessary either to change the json encoding method "schemas" in a specific place, but you can not directly affect the parent and child elements). Or it is necessary to use snake_case in the places where the link is written "$ref", which must be taken from the same global settings of the json encoder. Снимок экрана 2024-04-04 в 00 25 22

dankinsoid commented 5 months ago

@LukisMaster hm, I think a request returning swagger.json should use an encoder without any configurations, because OpenAPI models must be encoded as is

LukisMaster commented 5 months ago

@dankinsoid I totally agree with you. The only thing I do not know is how to do this just to respond to the request swagger.json. This global setting is appropriate for all queries in the entire project, which is very convenient. We write the names of the fields in a typical swift-style camelCase. And these settings save a lot of lines of code and protects us from possible errors, as if we were writing CodingKeys manually or defining a json encoder for each request. It would be great if swagger.json could ignore this setting, but at the same time it would correctly indicate in our case the name of the model in PascalCase, and the fields of the model in snake_case (automatically, or using the settings you wrote above).

LukisMaster commented 5 months ago

@dankinsoid The problem was solved. In the case of using the global encoder and decoder settings for JSON, as in my case. It is necessary to use the settings for the Open API and at the same time to respond to the request to receive swagger.json use the default JSONEncoder. Below is an example of an implementation. Thanks for the tips. Снимок экрана 2024-04-09 в 21 17 15 Снимок экрана 2024-04-09 в 21 27 56 Снимок экрана 2024-04-09 в 21 35 14