From 46a5dce066cda6abb6c422e9b2306dfe357105ba Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Thu, 14 Aug 2025 12:02:51 -0700 Subject: [PATCH] Keep empty values when deserializing application/x-www-form-urlencoded Signed-off-by: Anders Kaseorg --- openapi_core/deserializing/media_types/util.py | 4 +++- .../test_media_types_deserializers.py | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/openapi_core/deserializing/media_types/util.py b/openapi_core/deserializing/media_types/util.py index 520e20b3..9c63ce69 100644 --- a/openapi_core/deserializing/media_types/util.py +++ b/openapi_core/deserializing/media_types/util.py @@ -44,7 +44,9 @@ def urlencoded_form_loads( value: bytes, **parameters: str ) -> Mapping[str, Any]: # only UTF-8 is conforming - return ImmutableMultiDict(parse_qsl(value.decode("utf-8"))) + return ImmutableMultiDict( + parse_qsl(value.decode("utf-8"), keep_blank_values=True) + ) def data_form_loads(value: bytes, **parameters: str) -> Mapping[str, Any]: diff --git a/tests/unit/deserializing/test_media_types_deserializers.py b/tests/unit/deserializing/test_media_types_deserializers.py index 5b8104a2..53b43c35 100644 --- a/tests/unit/deserializing/test_media_types_deserializers.py +++ b/tests/unit/deserializing/test_media_types_deserializers.py @@ -201,6 +201,24 @@ def test_urlencoded_form_empty(self, deserializer_factory): assert result == {} + def test_urlencoded_form_empty_value(self, deserializer_factory): + mimetype = "application/x-www-form-urlencoded" + schema_dict = { + "type": "object", + "properties": { + "name": { + "type": "string", + }, + }, + } + schema = SchemaPath.from_dict(schema_dict) + deserializer = deserializer_factory(mimetype, schema=schema) + value = b"name=" + + result = deserializer.deserialize(value) + + assert result == {"name": ""} + def test_urlencoded_form_simple(self, deserializer_factory): mimetype = "application/x-www-form-urlencoded" schema_dict = {