@@ -112,6 +112,74 @@ pub struct BatchItemFailure {
112112 pub item_identifier : String ,
113113}
114114
115+ /// The Event sent to Lambda from the SQS API. Contains 1 or more individual SQS Messages
116+ #[ derive( Clone , Debug , Default , Deserialize , Eq , PartialEq , Serialize ) ]
117+ #[ serde( rename_all = "PascalCase" ) ]
118+ #[ serde( bound( deserialize = "T: DeserializeOwned" ) ) ]
119+ pub struct SqsApiEventObj < T : Serialize > {
120+ #[ serde( bound( deserialize = "T: DeserializeOwned" ) ) ]
121+ pub messages : Vec < SqsApiMessageObj < T > > ,
122+ }
123+
124+ /// The Event sent to Lambda from SQS API. Contains 1 or more individual SQS Messages
125+ #[ derive( Clone , Debug , Default , Deserialize , Eq , PartialEq , Serialize ) ]
126+ #[ serde( rename_all = "camelCase" ) ]
127+ pub struct SqsApiEvent {
128+ pub messages : Vec < SqsApiMessage > ,
129+ }
130+
131+ /// Alternative to SqsApiEvent to be used alongside SqsApiMessageObj<T> when you need to
132+ /// deserialize a nested object into a struct of type T within the SQS Message rather
133+ /// than just using the raw SQS Message string
134+ #[ serde_with:: serde_as]
135+ #[ derive( Clone , Debug , Default , Deserialize , Eq , PartialEq , Serialize ) ]
136+ #[ serde( bound( deserialize = "T: DeserializeOwned" ) ) ]
137+ #[ serde( rename_all = "PascalCase" ) ]
138+ pub struct SqsApiMessageObj < T : Serialize > {
139+ /// nolint: stylecheck
140+ #[ serde( default ) ]
141+ pub message_id : Option < String > ,
142+ #[ serde( default ) ]
143+ pub receipt_handle : Option < String > ,
144+ /// Deserialized into a `T` from nested JSON inside the SQS body string. `T` must implement the `Deserialize` or `DeserializeOwned` trait.
145+ #[ serde_as( as = "serde_with::json::JsonString" ) ]
146+ #[ serde( bound( deserialize = "T: DeserializeOwned" ) ) ]
147+ pub body : T ,
148+ #[ serde( default ) ]
149+ pub md5_of_body : Option < String > ,
150+ #[ serde( default ) ]
151+ pub md5_of_message_attributes : Option < String > ,
152+ #[ serde( deserialize_with = "deserialize_lambda_map" ) ]
153+ #[ serde( default ) ]
154+ pub attributes : HashMap < String , String > ,
155+ #[ serde( deserialize_with = "deserialize_lambda_map" ) ]
156+ #[ serde( default ) ]
157+ pub message_attributes : HashMap < String , SqsMessageAttribute > ,
158+ }
159+
160+ /// An individual SQS API Message, its metadata, and Message Attributes
161+ #[ derive( Clone , Debug , Default , Deserialize , Eq , PartialEq , Serialize ) ]
162+ #[ serde( rename_all = "PascalCase" ) ]
163+ pub struct SqsApiMessage {
164+ /// nolint: stylecheck
165+ #[ serde( default ) ]
166+ pub message_id : Option < String > ,
167+ #[ serde( default ) ]
168+ pub receipt_handle : Option < String > ,
169+ #[ serde( default ) ]
170+ pub body : Option < String > ,
171+ #[ serde( default ) ]
172+ pub md5_of_body : Option < String > ,
173+ #[ serde( default ) ]
174+ pub md5_of_message_attributes : Option < String > ,
175+ #[ serde( deserialize_with = "deserialize_lambda_map" ) ]
176+ #[ serde( default ) ]
177+ pub attributes : HashMap < String , String > ,
178+ #[ serde( deserialize_with = "deserialize_lambda_map" ) ]
179+ #[ serde( default ) ]
180+ pub message_attributes : HashMap < String , SqsMessageAttribute > ,
181+ }
182+
115183#[ cfg( test) ]
116184mod test {
117185 use super :: * ;
@@ -159,4 +227,26 @@ mod test {
159227 let reparsed: SqsBatchResponse = serde_json:: from_slice ( output. as_bytes ( ) ) . unwrap ( ) ;
160228 assert_eq ! ( parsed, reparsed) ;
161229 }
230+
231+ #[ test]
232+ #[ cfg( feature = "sqs" ) ]
233+ fn example_sqs_api_obj_event ( ) {
234+ // Example sqs api receive message response, fetched 2023-10-23, inspired from:
235+ // https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html#API_ReceiveMessage_ResponseSyntax
236+ #[ derive( Serialize , Deserialize , Debug , Eq , PartialEq ) ]
237+ struct CustStruct {
238+ city : String ,
239+ country : String ,
240+ }
241+
242+ let data = include_bytes ! ( "../../fixtures/example-sqs-api-event-obj.json" ) ;
243+ let parsed: SqsApiEventObj < CustStruct > = serde_json:: from_slice ( data) . unwrap ( ) ;
244+
245+ assert_eq ! ( parsed. messages[ 0 ] . body. city, "provincetown" ) ;
246+ assert_eq ! ( parsed. messages[ 0 ] . body. country, "usa" ) ;
247+
248+ let output: String = serde_json:: to_string ( & parsed) . unwrap ( ) ;
249+ let reparsed: SqsApiEventObj < CustStruct > = serde_json:: from_slice ( output. as_bytes ( ) ) . unwrap ( ) ;
250+ assert_eq ! ( parsed, reparsed) ;
251+ }
162252}
0 commit comments