openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[Python] boolean query parameter capitalization

Open ryanfox opened this issue 7 years ago • 6 comments

(Copy of https://github.com/swagger-api/swagger-codegen/issues/8433)

Description

The generated python client translates boolean query parameters in Python case - i.e. "True"/"False" rather than "true"/"false".

I am dealing with a case-sensitive API endpoint, which expects a boolean query parameter, and treats anything except "0" and "false" as true - including "False" evaluating to true.

Per RFC 3986, the query part of a URI should be treated as case-sensitive. I suspect many (most?) servers in the wild expect "false", in line with the variable names in most languages.

Is this expected behavior?

Swagger-codegen version

2.4.0-SNAPSHOT

Swagger declaration file content or url

        "parameters": [
          {
            "name": "reverse",
            "in": "query",
            "description": "If true, will sort results newest first.",
            "required": false,
            "default": false,
            "type": "boolean"
          }
        ],

Command line used for generation

java -jar ./swagger-codegen/modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i ./swagger.json -l python -o generated/python

Steps to reproduce

# given an API endpoint which accepts a boolean query parameter
>>> foo_list = client.Foo.Foo_get(reverse=True)
>>> foo_list.future.request.prepare()
>>> print(foo_list.url)
http://example.com/api/foo?reverse=True

Suggest a fix/enhancement

Suggestion: instead of "True" or "False", convert to the string "true" or "false".

ryanfox avatar Oct 17 '18 17:10 ryanfox

@ryanfox one workaround is to document the query parameter as a string instead of boolean and users will need to input either "true" or "false"

Another way is to use customized templates with the -t option and add logic to normalize the values inside the following mustache tag:

{{#isBoolean}}
...
{{/isBoolean}}

wing328 avatar Oct 19 '18 06:10 wing328

Thanks for the info. That's not going to work for the use case I am working with - what do you think the chances are of implementing a fix?

In any case, good to know there is a workaround.

ryanfox avatar Oct 22 '18 20:10 ryanfox

@ryanfox why would the string solution not work in your use case? Why not make it a string enum?

      - name: "reverse"
        in: "query"
        description: 'If true, will sort results newest first.'
        required: false
        default: "false"
        type: "string"
        enum:
        - "true"
        - "false"

spacether avatar Dec 09 '19 18:12 spacether

@spacether Perhaps because it adds a lot of noise to the spec, lies to every tool involved including the API generator, and generally just smells of a massive, dirty hack? :))

mcejp avatar Mar 15 '21 08:03 mcejp

Not saying that it shouldn't be fixed. My goal was to provide solution that unblocks Ryan. We welcome any PRs that fix issues. Do you want to work on fixing this @ryanfox or @mcejp ?

spacether avatar Mar 15 '21 19:03 spacether

For context here, I have yet to see an RFC that:

  • allows booleans as query parameters
  • defines what the behavior should be

If anyone knows of one, please do let me and the other maintainers know. So as far as I can see, this requested behavior has no generally agreed upon RFC spec defining boolean query parameter behavior. one could send ?someVal (presence) or ?someVal=true (pass by value) Note: If one sent someVal=true it is unclear if someVal has a boolean or a string value if the deserializing schema allows type string and boolean types. The relevant rfc that I know is RFC 6570

Related issues:

  • https://github.com/OpenAPITools/openapi-generator/issues/11683
  • https://github.com/OpenAPITools/openapi-generator/issues/10787
  • https://github.com/OpenAPITools/openapi-generator/issues/9709

spacether avatar Sep 16 '22 18:09 spacether

@ryanfox one workaround is to document the query parameter as a string instead of boolean and users will need to input either "true" or "false"

Another way is to use customized templates with the -t option and add logic to normalize the values inside the following mustache tag:

{{#isBoolean}}
...
{{/isBoolean}}

@wing328 I would be very interested for a patch for the template

NaKroTeK avatar Sep 30 '22 09:09 NaKroTeK

FYI a quick & dirty (or not) way after generating templates with java -jar openapi-generator-cli-6.0.1.jar author template -g python --library webclient i don't know what --library webclient really represent or anyother option...

I patched api_client.mustache like so in def sanitize_for_serialization(cls, obj):

        # bool first because a bool is also an int...
        elif isinstance(obj, bool):
            return obj.__str__().lower()
        elif isinstance(obj, (str, int, float, none_type)):

NaKroTeK avatar Sep 30 '22 14:09 NaKroTeK