Open Santobert opened 1 year ago
the older generator is still being worked on in a new repo here: https://github.com/openapi-json-schema-tools/openapi-json-schema-generator and it allows AnyType schemas + complex composition
Fyi, you openapi document looks wrong:
properties:
name:
type: object
description: "A string, a number or a boolean"
anyOf:
- type: string
- type: integer
format: int64
- type: number
format: double
- type: boolean
--> in a map there is a property called name with a value that is also a map that value must also meet these requirements. One or more of these schemas must validate the map payload:
because the value of name is already type object (which is a map or dict in python) it will never be a string/int/number/boolean and validation of this schema will never pass. If you need the values in the map to be string/int/number/boolean then move your anyOf schema definition like so:
name:
type: object
additionalProperties:
anyOf:
- type: string
- type: integer
format: int64
- type: number
format: double
- type: boolean
If you need name to be those values then remove the type object constraint like so:
name:
anyOf:
- type: string
- type: integer
format: int64
- type: number
format: double
- type: boolean
Thank you very much for your answer. Unfortunately, the openapi.yaml is generated by swagger itself (https://github.com/swagger-api/swagger-core). The underlying Java code is as follows:
public class Pet{
private Long id;
@Schema(description = "A string, a number or a boolean")
// anyOf = { String.class, Long.class, Double.class, Boolean.class }
private Object name;
}
In Java, String
, Long
, Double
, and Boolean
are also objects of type object
. So the problem boils down to the difference between primitives and objects in Java and Python. Is this something that the Python generator can solve, or is this a swagger issue?
Additionally, I tested your suggestion with my minimal example: https://gist.github.com/Santobert/0b93ef7233e0dfbbba580203fad5c9ce#file-openapi_suggestion-yaml
It still throws an error:
pydantic.error_wrappers.ValidationError: 1 validation error for Pet
name
value is not a valid dict (type=type_error.dict)
The generated python code is the same as before:
class PetName(BaseModel):
"""
A string, a number or a boolean
"""
# data type: str
anyof_schema_1_validator: Optional[StrictStr] = None
# data type: int
anyof_schema_2_validator: Optional[StrictInt] = None
# data type: float
anyof_schema_3_validator: Optional[Union[StrictFloat, StrictInt]] = None
# data type: bool
anyof_schema_4_validator: Optional[StrictBool] = None
actual_instance: Any
any_of_schemas: List[str] = Field(PETNAME_ANY_OF_SCHEMAS, const=True)
There are multiple issues at play here
How about trying my suggested spec (name is anyOf only with no object constraint) with this generator? https://github.com/openapi-json-schema-tools/openapi-json-schema-generator It will work.
I've submitted the issue here: https://github.com/swagger-api/swagger-core/issues/4457
Thanks for your help, I'll try the openapi-json-schema-generator soon.
Bug Report Checklist
Description
The Python client expects a property of type
object
to be a dict, which seems to be compliant with the JSON schema specification.However, this causes problems in combination with e.g. a Java server, where everything can be an object. For example, the API might allow an attribute to be either a string, a boolean, or a number, which can't be handled by the Python client.
The provided example generates an error
value is not a valid dict (type=type_error.dict)
. Even if the object is explicitly annotated withanyOf
and the corresponding data types, the error is the same.openapi-generator version
7.0.0-beta
OpenAPI declaration file content or url
openapi.yaml
or with
anyOf
Generation Details
java -jar .\openapi-generator-cli-7.0.0-beta.jar generate -i .\openapi.yaml -g python -o .\python\
Steps to reproduce
python -m venv venv
pip install .\python\
Related issues/PRs
Suggest a fix
It seems to me that the client is generated according to the JSON schema specification, however this is useless in the scenario shown above. The old python client
python-prior
allowed an object to be anything. Personally, I think this should be the desired behavior with the new client as well.