1use crate::syntax::*;
2use crate::FILE_EXTENSION;
3use atelier_core::error::{ErrorKind, Result as ModelResult, ResultExt};
4use atelier_core::io::ModelWriter;
5use atelier_core::model::shapes::{
6 AppliedTraits, HasTraits, MemberShape, ShapeKind, TopLevelShape,
7};
8use atelier_core::model::values::{Number, Value as NodeValue};
9use atelier_core::model::{HasIdentity, Model, ShapeID};
10use atelier_core::syntax::{
11 MEMBER_COLLECTION_OPERATIONS, MEMBER_CREATE, MEMBER_DELETE, MEMBER_ERRORS, MEMBER_IDENTIFIERS,
12 MEMBER_INPUT, MEMBER_KEY, MEMBER_LIST, MEMBER_MEMBER, MEMBER_OPERATIONS, MEMBER_OUTPUT,
13 MEMBER_PUT, MEMBER_READ, MEMBER_RENAME, MEMBER_RESOURCES, MEMBER_UPDATE, MEMBER_VALUE,
14 MEMBER_VERSION, MODEL_METADATA, MODEL_SHAPES, SHAPE_APPLY, SHAPE_LIST, SHAPE_MAP,
15 SHAPE_OPERATION, SHAPE_RESOURCE, SHAPE_SERVICE, SHAPE_SET, SHAPE_STRUCTURE, SHAPE_UNION,
16};
17use serde_json::{to_writer, to_writer_pretty, Map, Number as JsonNumber, Value};
18use std::io::Write;
19
20#[allow(missing_debug_implementations)]
40pub struct JsonWriter {
41 pretty_print: bool,
42}
43
44pub fn model_to_json(model: &Model) -> Value {
56 let mut top: Map<String, Value> = Default::default();
57
58 let _ = top.insert(
59 ADD_MODEL_SMITHY_VERSION.to_string(),
60 Value::String(model.smithy_version().to_string()),
61 );
62
63 if model.has_metadata() {
64 let mut meta_map: Map<String, Value> = Default::default();
65 for (key, value) in model.metadata() {
66 let _ = meta_map.insert(key.to_string(), from_value(value));
67 }
68 let _ = top.insert(MODEL_METADATA.to_string(), Value::Object(meta_map));
69 }
70 let _ = top.insert(MODEL_SHAPES.to_string(), from_shapes(model));
71
72 Value::Object(top)
73}
74
75impl Default for JsonWriter {
80 fn default() -> Self {
81 Self {
82 pretty_print: false,
83 }
84 }
85}
86
87impl ModelWriter for JsonWriter {
88 fn write(&mut self, w: &mut impl Write, model: &Model) -> ModelResult<()> {
89 let json = model_to_json(model);
90
91 if self.pretty_print {
92 to_writer_pretty(w, &json)
93 .chain_err(|| ErrorKind::Serialization(FILE_EXTENSION.to_string()).to_string())
94 } else {
95 to_writer(w, &json)
96 .chain_err(|| ErrorKind::Serialization(FILE_EXTENSION.to_string()).to_string())
97 }
98 }
99}
100
101impl<'a> JsonWriter {
102 pub fn new(pretty_print: bool) -> Self {
103 Self { pretty_print }
104 }
105}
106
107fn from_shapes(model: &Model) -> Value {
112 let mut shape_map: Map<String, Value> = Default::default();
113 for shape in model.shapes() {
114 let _ = shape_map.insert(shape.id().to_string(), from_shape(shape));
115 }
116 Value::Object(shape_map)
117}
118
119fn from_shape(shape: &TopLevelShape) -> Value {
120 let mut shape_map: Map<String, Value> = Default::default();
121 if shape.has_traits() {
122 let _ = shape_map.insert(
123 ADD_SHAPE_KEY_TRAITS.to_string(),
124 from_traits(shape.traits()),
125 );
126 }
127 match shape.body() {
128 ShapeKind::Simple(v) => {
129 let _ = shape_map.insert(ADD_SHAPE_KEY_TYPE.to_string(), Value::String(v.to_string()));
130 }
131 ShapeKind::List(v) => {
132 let _ = shape_map.insert(
133 ADD_SHAPE_KEY_TYPE.to_string(),
134 Value::String(SHAPE_LIST.to_string()),
135 );
136 let _ = shape_map.insert(MEMBER_MEMBER.to_string(), from_member(v.member()));
137 }
138 ShapeKind::Set(v) => {
139 let _ = shape_map.insert(
140 ADD_SHAPE_KEY_TYPE.to_string(),
141 Value::String(SHAPE_SET.to_string()),
142 );
143 let _ = shape_map.insert(MEMBER_MEMBER.to_string(), from_member(v.member()));
144 }
145 ShapeKind::Map(v) => {
146 let _ = shape_map.insert(
147 ADD_SHAPE_KEY_TYPE.to_string(),
148 Value::String(SHAPE_MAP.to_string()),
149 );
150 let _ = shape_map.insert(MEMBER_KEY.to_string(), from_member(v.key()));
151 let _ = shape_map.insert(MEMBER_VALUE.to_string(), from_member(v.value()));
152 }
153 ShapeKind::Structure(v) => {
154 let _ = shape_map.insert(
155 ADD_SHAPE_KEY_TYPE.to_string(),
156 Value::String(SHAPE_STRUCTURE.to_string()),
157 );
158 if v.has_members() {
159 let _ =
160 shape_map.insert(ADD_SHAPE_KEY_MEMBERS.to_string(), from_members(v.members()));
161 }
162 }
163 ShapeKind::Union(v) => {
164 let _ = shape_map.insert(
165 ADD_SHAPE_KEY_TYPE.to_string(),
166 Value::String(SHAPE_UNION.to_string()),
167 );
168 if v.has_members() {
169 let _ =
170 shape_map.insert(ADD_SHAPE_KEY_MEMBERS.to_string(), from_members(v.members()));
171 }
172 }
173 ShapeKind::Service(v) => {
174 let _ = shape_map.insert(
175 ADD_SHAPE_KEY_TYPE.to_string(),
176 Value::String(SHAPE_SERVICE.to_string()),
177 );
178 let _ = shape_map.insert(
179 MEMBER_VERSION.to_string(),
180 Value::String(v.version().to_string()),
181 );
182 if v.has_operations() {
183 let _ = shape_map.insert(
184 MEMBER_OPERATIONS.to_string(),
185 Value::Array(v.operations().map(|o| from_reference(o)).collect()),
186 );
187 }
188 if v.has_resources() {
189 let _ = shape_map.insert(
190 MEMBER_RESOURCES.to_string(),
191 Value::Array(v.resources().map(|o| from_reference(o)).collect()),
192 );
193 }
194 if v.has_renames() {
195 let mut rename_map: Map<String, Value> = Default::default();
196 for (k, v) in v.renames() {
197 let _ = rename_map.insert(k.to_string(), Value::String(v.to_string()));
198 }
199 let _ = shape_map.insert(MEMBER_RENAME.to_string(), Value::Object(rename_map));
200 }
201 }
202 ShapeKind::Operation(v) => {
203 let _ = shape_map.insert(
204 ADD_SHAPE_KEY_TYPE.to_string(),
205 Value::String(SHAPE_OPERATION.to_string()),
206 );
207 if let Some(v) = v.input() {
208 let _ = shape_map.insert(MEMBER_INPUT.to_string(), from_reference(v));
209 }
210 if let Some(v) = v.output() {
211 let _ = shape_map.insert(MEMBER_OUTPUT.to_string(), from_reference(v));
212 }
213 if v.has_errors() {
214 let _ = shape_map.insert(
215 MEMBER_ERRORS.to_string(),
216 Value::Array(v.errors().map(|o| from_reference(o)).collect()),
217 );
218 }
219 }
220 ShapeKind::Resource(v) => {
221 let _ = shape_map.insert(
222 ADD_SHAPE_KEY_TYPE.to_string(),
223 Value::String(SHAPE_RESOURCE.to_string()),
224 );
225 if v.has_identifiers() {
226 let mut id_map: Map<String, Value> = Default::default();
227 for (id, ref_id) in v.identifiers() {
228 let _ = id_map.insert(id.to_string(), from_reference(ref_id));
229 }
230 let _ = shape_map.insert(MEMBER_IDENTIFIERS.to_string(), Value::Object(id_map));
231 }
232 if let Some(v) = v.create() {
233 let _ = shape_map.insert(MEMBER_CREATE.to_string(), from_reference(v));
234 }
235 if let Some(v) = v.put() {
236 let _ = shape_map.insert(MEMBER_PUT.to_string(), from_reference(v));
237 }
238 if let Some(v) = v.read() {
239 let _ = shape_map.insert(MEMBER_READ.to_string(), from_reference(v));
240 }
241 if let Some(v) = v.update() {
242 let _ = shape_map.insert(MEMBER_UPDATE.to_string(), from_reference(v));
243 }
244 if let Some(v) = v.delete() {
245 let _ = shape_map.insert(MEMBER_DELETE.to_string(), from_reference(v));
246 }
247 if let Some(v) = v.list() {
248 let _ = shape_map.insert(MEMBER_LIST.to_string(), from_reference(v));
249 }
250 if v.has_operations() {
251 let _ = shape_map.insert(
252 MEMBER_OPERATIONS.to_string(),
253 Value::Array(v.operations().map(|o| from_reference(o)).collect()),
254 );
255 }
256 if v.has_collection_operations() {
257 let _ = shape_map.insert(
258 MEMBER_COLLECTION_OPERATIONS.to_string(),
259 Value::Array(
260 v.collection_operations()
261 .map(|o| from_reference(o))
262 .collect(),
263 ),
264 );
265 }
266 if v.has_resources() {
267 let _ = shape_map.insert(
268 MEMBER_RESOURCES.to_string(),
269 Value::Array(v.resources().map(|o| from_reference(o)).collect()),
270 );
271 }
272 }
273 ShapeKind::Unresolved => {
274 let _ = shape_map.insert(
275 ADD_SHAPE_KEY_TYPE.to_string(),
276 Value::String(SHAPE_APPLY.to_string()),
277 );
278 }
279 }
280 Value::Object(shape_map)
281}
282
283fn from_traits(traits: &AppliedTraits) -> Value {
284 let mut trait_map: Map<String, Value> = Default::default();
285 for (id, value) in traits {
286 let _ = trait_map.insert(
287 id.to_string(),
288 match value {
289 None => Value::Object(Default::default()),
290 Some(value) => from_value(value),
291 },
292 );
293 }
294 Value::Object(trait_map)
295}
296
297fn from_members<'a>(members: impl Iterator<Item = &'a MemberShape>) -> Value {
298 let mut members_map: Map<String, Value> = Default::default();
299 for member in members {
300 let _ = members_map.insert(member.id().to_string(), from_member(member));
301 }
302 Value::Object(members_map)
303}
304
305fn from_member(member: &MemberShape) -> Value {
306 let mut member_map: Map<String, Value> = Default::default();
307 let _ = member_map.insert(
308 ADD_SHAPE_KEY_TARGET.to_string(),
309 Value::String(member.target().to_string()),
310 );
311 if member.has_traits() {
312 let _ = member_map.insert(
313 ADD_SHAPE_KEY_TRAITS.to_string(),
314 from_traits(member.traits()),
315 );
316 }
317 Value::Object(member_map)
318}
319
320fn from_value(value: &NodeValue) -> Value {
321 match value {
322 NodeValue::None => Value::Null,
323 NodeValue::Array(v) => Value::Array(v.iter().map(|v| from_value(v)).collect()),
324 NodeValue::Object(v) => {
325 let mut object: Map<String, Value> = Default::default();
326 for (k, v) in v {
327 let _ = object.insert(k.clone(), from_value(v));
328 }
329 Value::Object(object)
330 }
331 NodeValue::Number(v) => match v {
332 Number::Integer(v) => Value::Number((*v).into()),
333 Number::Float(v) => Value::Number(JsonNumber::from_f64(*v).unwrap()),
334 },
335 NodeValue::Boolean(v) => Value::Bool(*v),
336 NodeValue::String(v) => Value::String(v.clone()),
337 }
338}
339
340fn from_reference(id: &ShapeID) -> Value {
341 let mut shape_map: Map<String, Value> = Default::default();
342 let _ = shape_map.insert(
343 ADD_SHAPE_KEY_TARGET.to_string(),
344 Value::String(id.to_string()),
345 );
346 Value::Object(shape_map)
347}