metaMeddl
metaMeddl

Reputation: 5

Pydantic to JSON Schema translation: How to write a field with no default value that is not required in the JSON schema?

I am using Pydantic 2.6.4 to generate JSON schemas for web forms, using React as the front-end framework. How do I write a field in a Pydantic model that has no default value but is not included in the "required" list in the translated JSON schema?

Consider the following schema:

{
  "title": "Cell",
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "type": {
      "type": "string"
    },
    "organism": {
      "type": "string"
    }
  },
  "required": ["name", "type"]
}

The property "organism" has no default value, and is not "required". It seems impossible to write a Pydantic model that will translate to the above schema. If you have no default value in Pydantic, it will be required in JSON and vice versa. Translating the above schema to Pydantic using datamodel-code-generator gives:

class Cell(BaseModel):
    name: str
    type: str
    organism: Optional[str] = None

But if I were to have written that in Pydantic originally, that is translated by Pydantic into JSON schema as:

"organism": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Organism"

Using the above schema on a webform on the front-end with React results in a drop-down menu for the two types, and not an empty box that the user can choose not to enter anything into and which will not be included in the form data, which is what I want.

Upvotes: 0

Views: 522

Answers (1)

Yurii Motov
Yurii Motov

Reputation: 2353

from pydantic import BaseModel, Field
from pydantic.json_schema import SkipJsonSchema

class Cell(BaseModel):
    name: str
    type: str
    organism: str | SkipJsonSchema[None] = Field(None, json_schema_extra=lambda x: x.pop("default"))


print(Cell.model_json_schema())

Output:

{
    'properties': {
        'name': {
            'title': 'Name',
            'type': 'string'
        },
        'type': {
            'title': 'Type',
            'type': 'string'
        },
        'organism': {
            'title': 'Organism',
            'type': 'string'
        }
    },
    'required': ['name', 'type'],
    'title': 'Cell',
    'type': 'object'
}

Upvotes: 1

Related Questions