yaml2json_rs/lib.rs
1use crate::Style::{COMPACT, PRETTY};
2use core::fmt::Debug;
3use std::io;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
7pub enum Yaml2JsonError {
8 #[error(transparent)]
9 SerdeYamlError(#[from] serde_yaml::Error),
10
11 #[error(transparent)]
12 SerdeJsonError(#[from] serde_json::Error),
13
14 #[error(transparent)]
15 IOError(#[from] io::Error),
16}
17
18/// `Style` defines JSON output formats for `Yaml2Json`.
19pub enum Style {
20 /// `Style::COMPACT` outputs JSON on a single line.
21 /// e.g. for the following YAML:
22 /// ```yaml
23 /// ---
24 /// hello: world
25 /// spec:
26 /// items:
27 /// - a
28 /// - b
29 /// ```
30 ///
31 /// the JSON output will be:
32 /// ```json
33 /// {"hello":"world","spec":{"items":["a","b"]}}
34 /// ```
35 COMPACT,
36 /// `Style::PRETTY` outputs JSON on multiple lines, with automatic indentation.
37 /// e.g. for the following YAML:
38 /// ```yaml
39 /// ---
40 /// hello: world
41 /// spec:
42 /// items:
43 /// - a
44 /// - b
45 /// ```
46 ///
47 /// the JSON output will be:
48 /// ```json
49 /// {
50 /// "hello": "world",
51 /// "spec": {
52 /// "items": [
53 /// "a",
54 /// "b"
55 /// ]
56 /// }
57 /// }
58 /// ```
59 PRETTY,
60}
61
62/// Yaml2Json can convert individual YAML documents into JSON. Each instance can be configured to
63/// have different styles of output.
64///
65/// The JSON output can be returned as a string:
66/// ```
67/// use yaml2json_rs::{Yaml2Json, Style};
68///
69/// let y2j = Yaml2Json::new(Style::COMPACT);
70/// let input = "hello: world";
71/// let output = y2j.document_to_string(input).unwrap();
72///
73/// assert_eq!(output, r#"{"hello":"world"}"#);
74/// ```
75///
76/// Or, the JSON output can be sent to a writer:
77/// ```
78/// use yaml2json_rs::{Yaml2Json, Style};
79/// use std::io;
80///
81/// let y2j = Yaml2Json::new(Style::COMPACT);
82/// let input = "hello: world";
83/// let mut stdout = io::stdout();
84///
85/// y2j.document_to_writer(input, &mut stdout).unwrap();
86///
87/// // {"hello":"world"}
88/// ```
89pub struct Yaml2Json {
90 style: Style,
91}
92
93impl Yaml2Json {
94 /// `new()` creates a new `Yaml2Json`. It expects you to provide an output `Style`.
95 /// ```
96 /// use yaml2json_rs::{Yaml2Json, Style};
97 ///
98 /// let y2j_pretty = Yaml2Json::new(Style::PRETTY);
99 /// let y2j_compact = Yaml2Json::new(Style::COMPACT);
100 /// ```
101 pub fn new(style: Style) -> Self {
102 Self { style }
103 }
104
105 /// `document_to_string()` takes a YAML document &str and converts it to a JSON String.
106 /// ```
107 /// use yaml2json_rs::{Yaml2Json, Style};
108 ///
109 /// let y2j = Yaml2Json::new(Style::COMPACT);
110 /// let input = "hello: world";
111 /// let output = y2j.document_to_string(input).unwrap();
112 ///
113 /// assert_eq!(output, r#"{"hello":"world"}"#);
114 /// ```
115 pub fn document_to_string(&self, document: &str) -> Result<String, Yaml2JsonError> {
116 let s: serde_json::Value = serde_yaml::from_str(document)?;
117
118 let res = match self.style {
119 COMPACT => serde_json::to_string(&s),
120 PRETTY => serde_json::to_string_pretty(&s),
121 };
122
123 match res {
124 Ok(s) => Ok(s),
125 Err(e) => Err(e.into()),
126 }
127 }
128
129 /// `document_to_writer()` takes a YAML document string, converts it to JSON and sends the output
130 /// to the provided writer.
131 ///
132 /// ```
133 /// use yaml2json_rs::{Yaml2Json, Style};
134 /// use std::io;
135 ///
136 /// let y2j = Yaml2Json::new(Style::COMPACT);
137 /// let input = "hello: world";
138 /// let mut stdout = io::stdout();
139 ///
140 /// y2j.document_to_writer(input, &mut stdout).unwrap();
141 ///
142 /// // {"hello":"world"}
143 /// ```
144 pub fn document_to_writer<W: io::Write>(
145 &self,
146 document: &str,
147 w: &mut W,
148 ) -> Result<(), Yaml2JsonError> {
149 let s: serde_json::Value = serde_yaml::from_str(document)?;
150
151 let res = match self.style {
152 PRETTY => serde_json::to_writer_pretty(w, &s),
153 COMPACT => serde_json::to_writer(w, &s),
154 };
155
156 match res {
157 Ok(_) => Ok(()),
158 Err(e) => Err(e.into()),
159 }
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use crate::{Style, Yaml2Json};
166 use std::io::Cursor;
167
168 #[test]
169 fn document_to_string_compact() {
170 let yaml2json = Yaml2Json::new(Style::COMPACT);
171 let input = r#"
172---
173abc: def
174"#;
175 let expected = r#"{"abc":"def"}"#;
176 let res = yaml2json.document_to_string(input).unwrap();
177 assert_eq!(expected, res);
178 }
179
180 #[test]
181 fn document_to_string_pretty() {
182 let yaml2json = Yaml2Json::new(Style::PRETTY);
183 let input = r#"
184---
185abc: def
186"#;
187 let expected = r#"{
188 "abc": "def"
189}"#;
190 let res = yaml2json.document_to_string(input).unwrap();
191 assert_eq!(expected, res);
192 }
193
194 #[test]
195 fn document_to_writer_compact() {
196 let yaml2json = Yaml2Json::new(Style::COMPACT);
197 let input = r#"
198---
199abc: def
200"#;
201 let expected = r#"{"abc":"def"}"#;
202
203 let mut buf = Cursor::new(Vec::<u8>::new());
204 yaml2json.document_to_writer(input, buf.get_mut()).unwrap();
205
206 let res = String::from_utf8(buf.into_inner()).unwrap();
207 assert_eq!(expected, res);
208 }
209
210 #[test]
211 fn document_to_writer_pretty() {
212 let yaml2json = Yaml2Json::new(Style::PRETTY);
213 let input = r#"
214---
215abc: def
216"#;
217 let expected = r#"{
218 "abc": "def"
219}"#;
220
221 let mut buf = Cursor::new(Vec::<u8>::new());
222 yaml2json.document_to_writer(input, buf.get_mut()).unwrap();
223
224 let res = String::from_utf8(buf.into_inner()).unwrap();
225 assert_eq!(expected, res);
226 }
227}