@@ -35,7 +35,11 @@ def __new__(cls, name, bases, dct):
3535 # Lists need to be normalized too as potentially we need to add a boolean flag to use FastList
3636 if v == FastList :
3737 raise TypeError (f"{ v } annotation is not supported without args" )
38- if CspTypingUtils .is_generic_container (v ) or CspTypingUtils .is_union_type (v ):
38+ if (
39+ CspTypingUtils .is_generic_container (v )
40+ or CspTypingUtils .is_union_type (v )
41+ or CspTypingUtils .is_literal_type (v )
42+ ):
3943 actual_type = ContainerTypeNormalizer .normalized_type_to_actual_python_type (v )
4044 if CspTypingUtils .is_generic_container (actual_type ):
4145 raise TypeError (f"{ v } annotation is not supported as a struct field [{ actual_type } ]" )
@@ -147,6 +151,17 @@ def serializer(val, handler):
147151
148152
149153class Struct (_csptypesimpl .PyStruct , metaclass = StructMeta ):
154+ @classmethod
155+ def type_adapter (cls ):
156+ # Late import to avoid autogen issues
157+ from pydantic import TypeAdapter
158+
159+ internal_type_adapter = getattr (cls , "_pydantic_type_adapter" , None )
160+ if internal_type_adapter :
161+ return internal_type_adapter
162+ cls ._pydantic_type_adapter = TypeAdapter (cls )
163+ return cls ._pydantic_type_adapter
164+
150165 @classmethod
151166 def metadata (cls , typed = False ):
152167 if typed :
@@ -191,7 +206,8 @@ def _obj_from_python(cls, json, obj_type):
191206 if CspTypingUtils .is_generic_container (obj_type ):
192207 if CspTypingUtils .get_origin (obj_type ) in (typing .List , typing .Set , typing .Tuple , FastList ):
193208 return_type = ContainerTypeNormalizer .normalized_type_to_actual_python_type (obj_type )
194- (expected_item_type ,) = obj_type .__args__
209+ # We only take the first item, so like for a Tuple, we would ignore arguments after
210+ expected_item_type = obj_type .__args__ [0 ]
195211 return_type = list if isinstance (return_type , list ) else return_type
196212 return return_type (cls ._obj_from_python (v , expected_item_type ) for v in json )
197213 elif CspTypingUtils .get_origin (obj_type ) is typing .Dict :
@@ -206,6 +222,13 @@ def _obj_from_python(cls, json, obj_type):
206222 return json
207223 else :
208224 raise NotImplementedError (f"Can not deserialize { obj_type } from json" )
225+ elif CspTypingUtils .is_union_type (obj_type ):
226+ return json ## no checks, just let it through
227+ elif CspTypingUtils .is_literal_type (obj_type ):
228+ return_type = ContainerTypeNormalizer .normalized_type_to_actual_python_type (obj_type )
229+ if isinstance (json , return_type ):
230+ return json
231+ raise ValueError (f"Expected type { return_type } received { json .__class__ } " )
209232 elif issubclass (obj_type , Struct ):
210233 if not isinstance (json , dict ):
211234 raise TypeError ("Representation of struct as json is expected to be of dict type" )
@@ -223,7 +246,9 @@ def _obj_from_python(cls, json, obj_type):
223246 return obj_type (json )
224247
225248 @classmethod
226- def from_dict (cls , json : dict ):
249+ def from_dict (cls , json : dict , use_pydantic : bool = False ):
250+ if use_pydantic :
251+ return cls .type_adapter ().validate_python (json )
227252 return cls ._obj_from_python (json , cls )
228253
229254 def to_dict_depr (self ):
0 commit comments