diff --git a/pydantic/json_schema.py b/pydantic/json_schema.py index c81a2899c3..b957846cef 100644 --- a/pydantic/json_schema.py +++ b/pydantic/json_schema.py @@ -1195,7 +1195,9 @@ def typed_dict_schema(self, schema: core_schema.TypedDictSchema) -> JsonSchemaVa with self._config_wrapper_stack.push(config): json_schema = self._named_required_fields_schema(named_required_fields) - extra = config.get('extra', 'ignore') + extra = schema.get('extra_behavior') + if extra is None: + extra = config.get('extra', 'ignore') if extra == 'forbid': json_schema['additionalProperties'] = False elif extra == 'allow': diff --git a/tests/test_json_schema.py b/tests/test_json_schema.py index 105732eb43..227e674d0f 100644 --- a/tests/test_json_schema.py +++ b/tests/test_json_schema.py @@ -2406,6 +2406,23 @@ class Model(TypedDict): } +def test_typeddict_with_extra_behavior_allow(): + class Model: + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + return core_schema.typed_dict_schema( + {'a': core_schema.typed_dict_field(core_schema.str_schema())}, + extra_behavior='allow', + ) + + assert TypeAdapter(Model).json_schema() == { + 'type': 'object', + 'properties': {'a': {'title': 'A', 'type': 'string'}}, + 'required': ['a'], + 'additionalProperties': True, + } + + def test_typeddict_with_extra_ignore(): class Model(TypedDict): __pydantic_config__ = ConfigDict(extra='ignore') # type: ignore @@ -2419,6 +2436,22 @@ class Model(TypedDict): } +def test_typeddict_with_extra_behavior_ignore(): + class Model: + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + return core_schema.typed_dict_schema( + {'a': core_schema.typed_dict_field(core_schema.str_schema())}, + extra_behavior='ignore', + ) + + assert TypeAdapter(Model).json_schema() == { + 'type': 'object', + 'properties': {'a': {'title': 'A', 'type': 'string'}}, + 'required': ['a'], + } + + def test_typeddict_with_extra_forbid(): @pydantic.dataclasses.dataclass class Model: @@ -2434,6 +2467,23 @@ class Model: } +def test_typeddict_with_extra_behavior_forbid(): + class Model: + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema: + return core_schema.typed_dict_schema( + {'a': core_schema.typed_dict_field(core_schema.str_schema())}, + extra_behavior='forbid', + ) + + assert TypeAdapter(Model).json_schema() == { + 'type': 'object', + 'properties': {'a': {'title': 'A', 'type': 'string'}}, + 'required': ['a'], + 'additionalProperties': False, + } + + @pytest.mark.parametrize( 'annotation,kwargs,field_schema', [