1use aws_smithy_schema::codec::Codec;
9use aws_smithy_schema::Schema;
10use aws_smithy_types::date_time::Format as TimestampFormat;
11use std::sync::Arc;
12
13mod deserializer;
14mod serializer;
15
16pub use deserializer::JsonDeserializer;
17pub use serializer::JsonSerializer;
18
19#[derive(Debug)]
25enum JsonFieldMapper {
26 UseMemberName,
28 UseJsonName,
30}
31
32impl JsonFieldMapper {
33 fn member_to_field<'a>(&self, member: &'a Schema) -> Option<&'a str> {
35 let name = member.member_name()?;
36 match self {
37 JsonFieldMapper::UseMemberName => Some(name),
38 JsonFieldMapper::UseJsonName => {
39 if let Some(jn) = member.json_name() {
40 return Some(jn.value());
41 }
42 Some(name)
43 }
44 }
45 }
46
47 fn field_to_member<'s>(&self, schema: &'s Schema, field_name: &str) -> Option<&'s Schema> {
49 match self {
50 JsonFieldMapper::UseMemberName => schema.member_schema(field_name),
51 JsonFieldMapper::UseJsonName => {
52 for member in schema.members() {
56 if let Some(jn) = member.json_name() {
57 if jn.value() == field_name {
58 return Some(member);
59 }
60 } else if member.member_name() == Some(field_name) {
61 return Some(member);
62 }
63 }
64 None
65 }
66 }
67 }
68}
69
70#[derive(Debug)]
81pub struct JsonCodecSettings {
82 field_mapper: JsonFieldMapper,
83 default_timestamp_format: TimestampFormat,
84}
85
86impl JsonCodecSettings {
87 pub fn builder() -> JsonCodecSettingsBuilder {
89 JsonCodecSettingsBuilder::default()
90 }
91
92 pub fn default_timestamp_format(&self) -> TimestampFormat {
94 self.default_timestamp_format
95 }
96
97 pub(crate) fn member_to_field<'a>(&self, member: &'a Schema) -> Option<&'a str> {
99 self.field_mapper.member_to_field(member)
100 }
101
102 pub(crate) fn field_to_member<'s>(
104 &self,
105 schema: &'s Schema,
106 field_name: &str,
107 ) -> Option<&'s Schema> {
108 self.field_mapper.field_to_member(schema, field_name)
109 }
110}
111
112impl Default for JsonCodecSettings {
113 fn default() -> Self {
114 Self {
115 field_mapper: JsonFieldMapper::UseJsonName,
116 default_timestamp_format: TimestampFormat::EpochSeconds,
117 }
118 }
119}
120
121#[derive(Debug, Clone)]
123pub struct JsonCodecSettingsBuilder {
124 use_json_name: bool,
125 default_timestamp_format: TimestampFormat,
126}
127
128impl Default for JsonCodecSettingsBuilder {
129 fn default() -> Self {
130 Self {
131 use_json_name: true,
132 default_timestamp_format: TimestampFormat::EpochSeconds,
133 }
134 }
135}
136
137impl JsonCodecSettingsBuilder {
138 pub fn use_json_name(mut self, value: bool) -> Self {
140 self.use_json_name = value;
141 self
142 }
143
144 pub fn default_timestamp_format(mut self, value: TimestampFormat) -> Self {
146 self.default_timestamp_format = value;
147 self
148 }
149
150 pub fn build(self) -> JsonCodecSettings {
152 let field_mapper = if self.use_json_name {
153 JsonFieldMapper::UseJsonName
154 } else {
155 JsonFieldMapper::UseMemberName
156 };
157 JsonCodecSettings {
158 field_mapper,
159 default_timestamp_format: self.default_timestamp_format,
160 }
161 }
162}
163
164#[derive(Debug)]
183pub struct JsonCodec {
184 settings: Arc<JsonCodecSettings>,
185}
186
187impl JsonCodec {
188 pub fn new(settings: JsonCodecSettings) -> Self {
190 Self {
191 settings: Arc::new(settings),
192 }
193 }
194
195 pub fn settings(&self) -> &JsonCodecSettings {
197 &self.settings
198 }
199}
200
201impl Default for JsonCodec {
202 fn default() -> Self {
203 Self::new(JsonCodecSettings::default())
204 }
205}
206
207impl Codec for JsonCodec {
208 type Serializer = JsonSerializer;
209 type Deserializer<'a> = JsonDeserializer<'a>;
210
211 fn create_serializer(&self) -> Self::Serializer {
212 JsonSerializer::new(self.settings.clone())
213 }
214
215 fn create_deserializer<'a>(&self, input: &'a [u8]) -> Self::Deserializer<'a> {
216 JsonDeserializer::new(input, self.settings.clone())
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use super::*;
223
224 #[test]
225 fn test_default_settings() {
226 let settings = JsonCodecSettings::default();
227 assert_eq!(
228 settings.default_timestamp_format(),
229 TimestampFormat::EpochSeconds
230 );
231 }
232
233 #[test]
234 fn test_builder() {
235 let settings = JsonCodecSettings::builder()
236 .use_json_name(false)
237 .default_timestamp_format(TimestampFormat::DateTime)
238 .build();
239 assert_eq!(
240 settings.default_timestamp_format(),
241 TimestampFormat::DateTime
242 );
243 }
244
245 #[test]
246 fn test_codec_creation() {
247 let codec = JsonCodec::default();
248 let _serializer = codec.create_serializer();
249 let _deserializer = codec.create_deserializer(b"{}");
250 }
251}