@@ -182,6 +182,59 @@ def func_with_str_types(str_or_list: str | list[str]): # pragma: no cover
182182 assert result ["str_or_list" ] == ["hello" , "world" ]
183183
184184
185+ def test_optional_str_preserves_json_strings ():
186+ """String-like unions should preserve JSON-looking strings as strings."""
187+
188+ def func_optional_str (config : str | None = None ):
189+ return config
190+
191+ meta = func_metadata (func_optional_str )
192+
193+ json_obj_str = '{"database": "postgres", "port": 5432}'
194+ result = meta .pre_parse_json ({"config" : json_obj_str })
195+ assert result ["config" ] == json_obj_str
196+ assert func_optional_str (result ["config" ]) == json_obj_str
197+
198+ json_array_str = '["item1", "item2", "item3"]'
199+ result = meta .pre_parse_json ({"config" : json_array_str })
200+ assert result ["config" ] == json_array_str
201+ assert func_optional_str (result ["config" ]) == json_array_str
202+
203+
204+ @pytest .mark .anyio
205+ async def test_optional_str_runtime_validation_preserves_json_string ():
206+ """Ensure optional string values reach the function without JSON pre-parsing."""
207+
208+ def handle_json_payload (payload : str | None = None ) -> str :
209+ assert isinstance (payload , str )
210+ return payload
211+
212+ meta = func_metadata (handle_json_payload )
213+ json_payload = '{"action": "create", "resource": "user"}'
214+
215+ result = await meta .call_fn_with_arg_validation (
216+ handle_json_payload ,
217+ fn_is_async = False ,
218+ arguments_to_validate = {"payload" : json_payload },
219+ arguments_to_pass_directly = None ,
220+ )
221+
222+ assert result == json_payload
223+
224+
225+ def test_optional_list_still_pre_parses_json_string ():
226+ """Complex optional types still accept JSON-encoded structured values."""
227+
228+ def func_optional_list (items : list [str ] | None = None ):
229+ return items
230+
231+ meta = func_metadata (func_optional_list )
232+
233+ result = meta .pre_parse_json ({"items" : '["hello", "world"]' })
234+ assert result ["items" ] == ["hello" , "world" ]
235+ assert func_optional_list (result ["items" ]) == ["hello" , "world" ]
236+
237+
185238def test_skip_names ():
186239 """Test that skipped parameters are not included in the model"""
187240
0 commit comments