I have a pydantic model ModelX, with member Enums defined. The script should run as is.
from enum import Enum from pydantic import BaseModel,Field,schema_json_of from typing import Optional class FirstEnumList(str, Enum): VAL1="VAL1" VAL2="VAL2" VAL3="VAL3" class SecondEnumList(str, Enum): VAL4="VAL4" VAL5="VAL5" class ModelX(BaseModel): V: Optional[FirstEnumList]=Field(FirstEnumList.VAL1, alias='value1') A: Optional[str] B: Optional[int] P: Optional[SecondEnumList]=Field(SecondEnumList.VAL4, alias='valueP') print (schema_json_of(ModelX)) '''Output below for schema_json_of {"title": "ParsingModel[ModelX]", "$ref": "#/definitions/ModelX", "definitions": { "FirstEnumList": { "title": "FirstEnumList", "description": "An enumeration.", "enum": ["VAL1", "VAL2", "VAL3"], "type": "string" }, "SecondEnumList": { "title": "SecondEnumList", "description": "An enumeration.", "enum": ["VAL4", "VAL5"], "type": "string" }, "ModelX": { "title": "ModelX", "type": "object", "properties": { "value1": { "default": "VAL1", "allOf": [{"$ref": "#/definitions/FirstEnumList"}] }, "A": { "title": "A", "type": "string" }, "B": { "title": "B", "type": "integer" }, "valueP": { "default": "VAL4", "allOf": [{"$ref": "#/definitions/SecondEnumList"}]} } } } } '''
I want to export this model as a JSON with the list of all Enum values. Something like
{ "value1": { "allOf": [ "VAL1", "VAL2", "VAL3" ] }, "A": { "type": "string" }, "B": { "type": "integer" }, "valueP": { "allOf": [ "VAL4", "VAL5" ] } }
I am looking to return this Json as a response of my api call, all Enum values, it can be under “allOf” key or some other better way. This way the response has all the possible enum values and the consumer of this response can use it to pre-validate requests, or even show them on a UI screen.
Let me know in case more details or explanation is required.
Advertisement
Answer
Pydantic is configured to export json schema compliant with the following specifications: JSON Schema Core, JSON Schema Validation, OpenAPI.
These specs follow the design principle of reducing repeated elements. Child models are referenced with ref
to avoid unnecessarily repeating model definitions.
You can override some elements of this by modifying a “sub-model” in the Field
class by adding a custom title or default value. Only the overloaded values however will be included.
In your case, you will need to employ a workaround to manipulate the final state:
my_schema = ModelX.schema() for k, v in my_schema["properties"].items(): if ('allOf' in v and len(v['allOf']) == 1 and isinstance(v['allOf'][0], dict) and v['allOf'][0].get('$ref') is not None ): # get the values enum_key = v['allOf'][0]['$ref'].replace('#/definitions/', '') enum_vals = my_schema['definitions'][enum_key]['enum'] # Set the values my_schema["properties"][k]['allOf'] = enum_vals # Get enum values print(my_schema) { "value1": { "title": "value1", "default": "VAL1", "allOf": [ "VAL1", "VAL2", "VAL3" ] }, "A": { "title": "A", "type": "string" }, "B": { "title": "B", "type": "integer" }, "valueP": { "default": "VAL4", "allOf": [ "VAL4", "VAL5" ] } }