Open
@Ark-kun

Description

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