@@ -390,7 +390,7 @@ def _jsoncompat_construct_value(annotation: Any, value: Any) -> Any:
390390 if isinstance (value , bool ):
391391 return value
392392 raise TypeError (f"expected bool, got { type (value ).__name__ } " )
393- if annotation is type (None ):
393+ if annotation is None or annotation is type (None ):
394394 if value is None :
395395 return None
396396 raise TypeError (f"expected null, got { type (value ).__name__ } " )
@@ -408,14 +408,26 @@ def _jsoncompat_construct_value(annotation: Any, value: Any) -> Any:
408408 _jsoncompat_construct_value (item_annotation , item )
409409 for item in value_items
410410 ]
411+ if origin is dict :
412+ key_annotation , value_annotation = _jsoncompat_dict_annotations (annotation )
413+ if not isinstance (value , dict ):
414+ raise TypeError (f"expected dict, got { type (value ).__name__ } " )
415+ value_object = cast (dict [Any , Any ], value )
416+ return {
417+ _jsoncompat_construct_value (key_annotation , key ): _jsoncompat_construct_value (
418+ value_annotation ,
419+ item ,
420+ )
421+ for key , item in value_object .items ()
422+ }
411423 if origin in {types .UnionType , Union }:
412424 return _jsoncompat_construct_union (get_args (annotation ), value )
413425 if origin is Literal :
414426 if value in get_args (annotation ):
415427 return value
416428 raise TypeError (f"expected one of { get_args (annotation )!r} , got { value !r} " )
417429
418- return value
430+ raise TypeError ( f"unsupported runtime annotation { annotation !r } " )
419431
420432
421433def _jsoncompat_construct_union (branches : tuple [Any , ...], value : Any ) -> Any :
@@ -504,6 +516,13 @@ def _jsoncompat_extra_value_annotation(annotation: Any) -> Any:
504516 return Any
505517
506518
519+ def _jsoncompat_dict_annotations (annotation : Any ) -> tuple [Any , Any ]:
520+ args = get_args (annotation )
521+ if len (args ) == 2 :
522+ return args [0 ], args [1 ]
523+ return Any , Any
524+
525+
507526def _jsoncompat_validate_python_value (annotation : Any , value : Any ) -> None :
508527 if annotation is Any :
509528 return
@@ -527,7 +546,7 @@ def _jsoncompat_validate_python_value(annotation: Any, value: Any) -> None:
527546 if isinstance (value , bool ):
528547 return
529548 raise TypeError (f"expected bool, got { type (value ).__name__ } " )
530- if annotation is type (None ):
549+ if annotation is None or annotation is type (None ):
531550 if value is None :
532551 return
533552 raise TypeError (f"expected null, got { type (value ).__name__ } " )
@@ -548,6 +567,15 @@ def _jsoncompat_validate_python_value(annotation: Any, value: Any) -> None:
548567 for item in value_items :
549568 _jsoncompat_validate_python_value (item_annotation , item )
550569 return
570+ if origin is dict :
571+ key_annotation , value_annotation = _jsoncompat_dict_annotations (annotation )
572+ if not isinstance (value , dict ):
573+ raise TypeError (f"expected dict, got { type (value ).__name__ } " )
574+ value_object = cast (dict [Any , Any ], value )
575+ for key , item in value_object .items ():
576+ _jsoncompat_validate_python_value (key_annotation , key )
577+ _jsoncompat_validate_python_value (value_annotation , item )
578+ return
551579 if origin in {types .UnionType , Union }:
552580 for branch in get_args (annotation ):
553581 try :
@@ -561,6 +589,8 @@ def _jsoncompat_validate_python_value(annotation: Any, value: Any) -> None:
561589 return
562590 raise TypeError (f"expected one of { get_args (annotation )!r} , got { value !r} " )
563591
592+ raise TypeError (f"unsupported runtime annotation { annotation !r} " )
593+
564594
565595def _jsoncompat_new_unchecked [JSONCOMPAT_MODEL_T : DataclassModel ](
566596 model_type : type [JSONCOMPAT_MODEL_T ],
0 commit comments