Skip to content

🧹 Clarification: Optional properties and null vs. undefined when used in languages like Python that only has a single None type #1586

Open
@Ark-kun

Description

@Ark-kun

Specification section

?

What is unclear?

Please help us.

Pydantic v2 started converting Python's Optional[str] type to {"anyOf":[{"type":"string"}, {"type":"null"}]} Json Schema instead of an optional string property.This breaks many existing tools that use JsonSchemas, but the maintainer claims that JsonSchema is designed this way. pydantic/pydantic#7161
Please help us get clarity whether this is really what Json Schema spec design intends.

I want to ask whether this is indeed the intention of JsonSchema design and if it's not the case, then hopefully the maintainers can be persuaded to restore the previous behavior.

Problem background:
Javascript has null and undefined types.
Python has None singleton type. It's automatically used in some cases. For example, when function does not return anything, the actual returned value is None.

Let's look at this simple JsonSchema that has an optional field:

{
  "title": "Something",
  "type": "object",
  "properties": {
    "requiredProp": {"type": "string"},
    "optionalProp": {"type": "string"},
  "required": [ "requiredProp"]
}

Now let's try to represent such schema using Python:

class Something:
  requiredProp: str
  optionalProp: Optional[str]

For this type, Pydantic v2 produces the following JsonSchema:

{
  "title": "Something",
  "type": "object",
  "properties": {
    "requiredProp": {
      "title": "Requiredprop",
      "type": "string"
    },
    "optionalProp": {
      "title": "Optionalprop",
      "anyOf": [
        {"type": "string"},
        {"type": "null"}
      ]
    }
  },
  "required": ["requiredProp", "optionalProp"]
}

Notice that the "optionalProp" is required and it's type declaration is {"anyOf":[{"type":"string"}, {"type":"null"}]}.

And if we slightly change the class to add the default value:

class Something:
  requiredProp: str
  optionalProp: Optional[str] = None

some_obj = Something(requiredProp="foo")

The generated schema becomes

{
  "title": "Something",
  "type": "object",
  "properties": {
    "requiredProp": {
      "title": "Requiredprop",
      "type": "string"
    },
    "optionalProp": {
      "title": "Optionalprop",
      "anyOf": [
        {"type": "string"},
        {"type": "null"}
      ]
    }
  },
  "required": ["requiredProp"]
}

The optionalProp type declaration still remains {"anyOf":[{"type":"string"}, {"type":"null"}]}.

So it's not possible to generate a normal optional string property.

Is it the intention of JsonSchema that programming languages that do not have the undefined/null duality of Javascript cannot adhere to simple JSON schemas with simple optional properties?

Would it be OK to treat Python's None as Javascript's undefined in cases of optional function/constructor parameters or are these types considered to be fundamentally different?

Proposal

I propose to clarify that in non-JS languages optional properties with the default None/NULL/nil value can be treated as Javascript's undefined and can be described using JsonSchema's optional property mechanism.

Do you think this work might require an [Architectural Decision Record (ADR)]? (significant or noteworthy)

No

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions