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 max_depth: u32,
85}
86
87impl JsonCodecSettings {
88 pub fn builder() -> JsonCodecSettingsBuilder {
90 JsonCodecSettingsBuilder::default()
91 }
92
93 pub fn default_timestamp_format(&self) -> TimestampFormat {
95 self.default_timestamp_format
96 }
97
98 pub fn max_depth(&self) -> u32 {
102 self.max_depth
103 }
104
105 pub(crate) fn member_to_field<'a>(&self, member: &'a Schema) -> Option<&'a str> {
107 self.field_mapper.member_to_field(member)
108 }
109
110 pub(crate) fn field_to_member<'s>(
112 &self,
113 schema: &'s Schema,
114 field_name: &str,
115 ) -> Option<&'s Schema> {
116 self.field_mapper.field_to_member(schema, field_name)
117 }
118}
119
120impl Default for JsonCodecSettings {
121 fn default() -> Self {
122 Self {
123 field_mapper: JsonFieldMapper::UseJsonName,
124 default_timestamp_format: TimestampFormat::EpochSeconds,
125 max_depth: crate::codec::deserializer::MAX_DESERIALIZE_DEPTH,
126 }
127 }
128}
129
130#[derive(Debug, Clone)]
132pub struct JsonCodecSettingsBuilder {
133 use_json_name: bool,
134 default_timestamp_format: TimestampFormat,
135 max_depth: u32,
136}
137
138impl Default for JsonCodecSettingsBuilder {
139 fn default() -> Self {
140 Self {
141 use_json_name: true,
142 default_timestamp_format: TimestampFormat::EpochSeconds,
143 max_depth: crate::codec::deserializer::MAX_DESERIALIZE_DEPTH,
144 }
145 }
146}
147
148impl JsonCodecSettingsBuilder {
149 pub fn use_json_name(mut self, value: bool) -> Self {
151 self.use_json_name = value;
152 self
153 }
154
155 pub fn default_timestamp_format(mut self, value: TimestampFormat) -> Self {
157 self.default_timestamp_format = value;
158 self
159 }
160
161 pub fn max_depth(mut self, value: u32) -> Self {
164 self.max_depth = value;
165 self
166 }
167
168 pub fn build(self) -> JsonCodecSettings {
170 let field_mapper = if self.use_json_name {
171 JsonFieldMapper::UseJsonName
172 } else {
173 JsonFieldMapper::UseMemberName
174 };
175 JsonCodecSettings {
176 field_mapper,
177 default_timestamp_format: self.default_timestamp_format,
178 max_depth: self.max_depth,
179 }
180 }
181}
182
183#[derive(Debug)]
202pub struct JsonCodec {
203 settings: Arc<JsonCodecSettings>,
204}
205
206impl JsonCodec {
207 pub fn new(settings: JsonCodecSettings) -> Self {
209 Self {
210 settings: Arc::new(settings),
211 }
212 }
213
214 pub fn settings(&self) -> &JsonCodecSettings {
216 &self.settings
217 }
218}
219
220impl Default for JsonCodec {
221 fn default() -> Self {
222 Self::new(JsonCodecSettings::default())
223 }
224}
225
226impl Codec for JsonCodec {
227 type Serializer = JsonSerializer;
228 type Deserializer<'a> = JsonDeserializer<'a>;
229
230 fn create_serializer(&self) -> Self::Serializer {
231 JsonSerializer::new(self.settings.clone())
232 }
233
234 fn create_deserializer<'a>(&self, input: &'a [u8]) -> Self::Deserializer<'a> {
235 JsonDeserializer::new(input, self.settings.clone())
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 #[test]
244 fn test_default_settings() {
245 let settings = JsonCodecSettings::default();
246 assert_eq!(
247 settings.default_timestamp_format(),
248 TimestampFormat::EpochSeconds
249 );
250 }
251
252 #[test]
253 fn test_builder() {
254 let settings = JsonCodecSettings::builder()
255 .use_json_name(false)
256 .default_timestamp_format(TimestampFormat::DateTime)
257 .build();
258 assert_eq!(
259 settings.default_timestamp_format(),
260 TimestampFormat::DateTime
261 );
262 }
263
264 #[test]
265 fn test_codec_creation() {
266 let codec = JsonCodec::default();
267 let _serializer = codec.create_serializer();
268 let _deserializer = codec.create_deserializer(b"{}");
269 }
270}