[BUG][python-flask] converting to and from dict with camelCase properties
Created by: Shogoki
Bug Report Checklist
-
Have you provided a full/minimal spec to reproduce the issue? -
Have you validated the input using an OpenAPI validator (example)? -
What's the version of OpenAPI Generator used? --> 4.2.1 -
Have you search for related issues/PRs? -
What's the actual output vs expected output?
Description
When i have a model defined in OpenAPI, which uses camelCase Properties the generator automatically converts the python props to pythonic snake_case Names. So far, so good.
When using the from_dict(dict) method of the Model class it is taking a dict with the snakeCase properties as Keys and converts them at instantiation. This is super cool and useful, as we can directly pass a dict, created from JSON payload, as is.
But, with an existing model, when I call the to_dict() method on it, i get a dict, which has the snake_case prop names as Key!
This means, that have inconsistency in converting a model to dict, and creating one from the dict again. as this will fail for all props having a camelCase name (see example). I believe this behaviour is not intended. I´d expect the to_dict() method to produce the camelCase prop names (which are available in the attribute_map anyway.
Example:
# create a new instance of MyModel
model = MyModel(demo_name="name", id=1)
# Property has snake_case Name: demoName --> demo_name
log.warn("Model is: {}".format(model))
# OUTPUT: WARNING in demo_controller: Model is: {'demo_name': 'name', 'id': 1}
# using to_dict method to get a dict from Model
model_dict = model.to_dict()
log.warn("Model.to_dict() is: {}".format(model_dict))
# OUTPUT: WARNING in demo_controller: Model.to_dict() is: {'demo_name': 'name', 'id': 1}
# now we want to convert that dict (probably fetched from DB) back to our Model
new_model = MyModel.from_dict(model_dict)
log.warn("New Created Model is: {}".format(new_model))
# OUTPUT: WARNING in demo_controller: New Created Model is: {'demo_name': None, 'id': 1}
# --> demo_name = None !!!!
openapi-generator version
4.2.1
OpenAPI declaration file content or url
openapi: 3.0.0
info:
title: DEMO for issue
version: "1.0"
servers:
- url: http://localhost:8080
tags:
- name: demo
paths:
/demo:
get:
operationId: get_demo
responses:
200:
content:
application/json:
schema:
$ref: '#/components/schemas/MyModel'
description: Demo Response
tags:
- demo
x-openapi-router-controller: openapi_server.controllers.demo_controller
components:
schemas:
MyModel:
example:
demoName: demoName
id: 0
properties:
demoName:
type: string
id:
type: integer
type: object
Command line used for generation
openapi-generator generate -g python-flask -i base_model_dict.yml -o api
Steps to reproduce
clone the demo api i build for reproducing this
git clone https://github.com/Shogoki/openapi-to_dict-demo.git
build and start the API
cd openapi-to_dict_demo && docker-compose up
in a Browser, or another terminal issue a GET call to localhost:8080/demo , e.g.
curl http://localhost:8080/demo
Watch the Log output of the API.
Related issues/PRs
don´t know...
Suggest a fix
I successfully fixed the issue in some of my projects by patching the to_dict method in base_model_.py as follows:
def to_dict(self):
"""Returns the model properties as a dict
:rtype: dict
"""
result = {}
for attr, _ in six.iteritems(self.openapi_types):
value = getattr(self, attr)
dict_attr = self.attribute_map[attr]
if isinstance(value, list):
result[dict_attr] = list(map(
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
value
))
elif hasattr(value, "to_dict"):
result[dict_attr] = value.to_dict()
elif isinstance(value, dict):
result[dict_attr] = dict(map(
lambda item: (item[0], item[1].to_dict())
if hasattr(item[1], "to_dict") else item,
value.items()
))
else:
result[dict_attr] = value
return result