'JSON Schema - nested property is required based on conditional

I tried to create a minimum viable example for this. What I want to achieve is the following:

  1. if json contains post, then make both a and b required in attrs
  2. if json contains patch then make neither of them required.
  3. Use datamodel-codegen to generate pydantic dataclasses based on this schema.

I believe that there is a way to validate by doing the following, however I can't do it this way. For some reason the model generator being used does not properly set the dataclass properties to required/optional when defined this way.

"attrs": {
    "additionalProperties": false,
    "properties": {
        "a": {
            "$ref": "#/$defs/a"
        },
        "b": {
            "$ref": "#/$defs/b"
        }
    }
},
"create": {
    "attrs": {
        "$ref": "#/$defs/attrs",
        "required": ["a", "b"]
    }
}

leads to

class A(BaseModel):
    __root__: str


class B(BaseModel):
    __root__: str


class Attrs(BaseModel):
    class Config:
        extra = Extra.forbid

    a: Optional[A] = None
    b: Optional[B] = None


class Create(BaseModel):
    attrs: Attrs


class Update(BaseModel):
    attrs: Optional[Attrs] = None


class Model(BaseModel):
    patch: Optional[Update] = None
    post: Optional[Create] = None

This is actually incorrect because it implies that each individual attribute is optional. I assume this is because of where in the schema I defined the required property.

Instead, I would like to see if there is a way to define the required and optional properties in the definition of attrs in the json schema.

This is the schema I made as a template as an example. I tried using if and then conditions but I couldn't figure it out.

{
    "properties": {
        "patch": {
            "$ref": "#/$defs/update"
        },
        "post": {
            "$ref": "#/$defs/create"
        }
    },
    "$defs": {
        "create": {
            "properties": {
                "attrs": {
                    "$ref": "#/$defs/attrs"
                }
            }
        },
        "update": {
            "properties": {
                "attrs": {
                    "$ref": "#/$defs/attrs"
                }
            }
        },
        "attrs": {
            "additionalProperties": false,
            "properties": {
                "a": {
                    "$ref": "#/$defs/a"
                },
                "b": {
                    "$ref": "#/$defs/b"
                }
            }
        },
        "a": {
            "type": "string"
        },
        "b": {
            "type": "string"
        }
    }
}

How can I define the required properties of attrs based on the conditional, that being that the top level property contains post or patch?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source