1- from typing import Optional , Set
1+ from typing import Optional , Set , Union
22import logging
33import json
44from datetime import datetime
5- from base64 import b64encode , b64decode
65
76import boto3
87from boto3 .dynamodb .conditions import Key , Attr
@@ -80,20 +79,16 @@ def _to_epoch_float(dt):
8079
8180SERIALIZE_MAP = {
8281 "number" : str , # float or decimal
83- "string" : lambda d : d .isoformat () if isinstance (d , datetime ) else d , # string, datetime
82+ "string" : str ,
83+ "string:date-time" : lambda d : d .isoformat (),
8484 "boolean" : lambda d : 1 if d else 0 ,
8585 "object" : json .dumps ,
8686 "array" : json .dumps ,
8787}
8888
8989
90- def do_nothing (x ):
91- return x
92-
93-
9490DESERIALIZE_MAP = {
9591 "number" : float ,
96- "string" : do_nothing ,
9792 "boolean" : bool ,
9893 "object" : json .loads ,
9994 "array" : json .loads ,
@@ -121,27 +116,44 @@ def __init__(self, schema):
121116 self .properties = schema ["properties" ]
122117 self .definitions = schema .get ("definitions" )
123118
124- def _get_type_possibilities (self , field_name ) -> Set [str ]:
119+ def _get_type_possibilities (self , field_name ) -> Set [tuple ]:
125120 field_properties = self .properties [field_name ]
126121
127122 possible_types = []
128123 if "anyOf" in field_properties :
129- possible_types .extend ([r .get ("$ref" , r . get ( "type" ) ) for r in field_properties ["anyOf" ]])
124+ possible_types .extend ([r .get ("$ref" , r ) for r in field_properties ["anyOf" ]])
130125 else :
131- possible_types .append (field_properties .get ("$ref" , field_properties .get ("type" )))
132- return set ([
133- (self .definitions [t .split ('/' )[- 1 ]].get ("type" ) if t .startswith ('#/' ) else t )
126+ possible_types .append (field_properties .get ("$ref" , field_properties ))
127+
128+ def type_from_definition (definition_signature : Union [str , dict ]) -> dict :
129+ if isinstance (definition_signature , str ):
130+ t = definition_signature .split ('/' )[- 1 ]
131+ return self .definitions [t ]
132+ return definition_signature
133+
134+ type_dicts = [
135+ type_from_definition (t )
134136 for t in possible_types
137+ ]
138+
139+ return set ([
140+ (t ['type' ], t .get ('format' , '' ))
141+ for t in type_dicts
135142 ])
136143
137144 def _serialize_field (self , field_name , value ):
138145 field_types = self ._get_type_possibilities (field_name )
139146 if value is not None :
140147 for t in field_types :
141148 try :
142- return SERIALIZE_MAP [t ](value )
149+ type_signature = ":" .join (t ).rstrip (':' )
150+ try :
151+ return SERIALIZE_MAP [type_signature ](value )
152+ except KeyError :
153+ return SERIALIZE_MAP [t [0 ]](value )
143154 except (ValueError , TypeError , KeyError ):
144155 pass
156+
145157 return value
146158
147159 def serialize_record (self , data_dict ) -> dict :
@@ -158,9 +170,14 @@ def _deserialize_field(self, field_name, value):
158170 if value is not None :
159171 for t in field_types :
160172 try :
161- return DESERIALIZE_MAP [t ](value )
173+ type_signature = ":" .join (t ).rstrip (':' )
174+ try :
175+ return DESERIALIZE_MAP [type_signature ](value )
176+ except KeyError :
177+ return DESERIALIZE_MAP [t [0 ]](value )
162178 except (ValueError , TypeError , KeyError ):
163179 pass
180+
164181 return value
165182
166183 def deserialize_record (self , data_dict ) -> dict :
0 commit comments