mik_sdk/json/
to_json.rs

1//! ToJson trait and all implementations.
2
3use super::builder::{arr, float, int, null, str};
4use super::value::JsonValue;
5
6/// A trait for converting types to JSON values.
7///
8/// This trait enables type inference in the `json!` and `ok!` macros,
9/// allowing you to write:
10///
11/// ```
12/// # use mik_sdk::json::{self, ToJson};
13/// let name = "Alice";
14/// let age = 30i64;
15/// let value = json::obj()
16///     .set("name", name.to_json())
17///     .set("age", age.to_json());
18/// assert!(value.to_string().contains("Alice"));
19/// ```
20///
21/// Instead of the more verbose:
22///
23/// ```
24/// # use mik_sdk::json;
25/// let name = "Alice";
26/// let age = 30;
27/// let value = json::obj()
28///     .set("name", json::str(name))
29///     .set("age", json::int(age));
30/// assert!(value.to_string().contains("Alice"));
31/// ```
32///
33/// # Implementations
34///
35/// This trait is implemented for:
36/// - Strings: `String`, `&str`, `&String`, `Cow<str>`
37/// - Integers: `i8`, `i16`, `i32`, `i64`, `u8`, `u16`, `u32`, `u64`, `usize`, `isize`
38/// - Floats: `f32`, `f64`
39/// - Boolean: `bool`
40/// - Optional: `Option<T>` where T: ToJson (None becomes null)
41/// - Arrays: `Vec<T>`, `&[T]` where T: ToJson
42/// - JSON: `JsonValue` (pass-through)
43///
44/// # Example
45///
46/// ```
47/// use mik_sdk::json::{self, ToJson};
48///
49/// let name = "Alice".to_string();
50/// let age = 30i64;
51/// let active = true;
52/// let tags: Vec<&str> = vec!["admin", "user"];
53///
54/// // All these types implement ToJson
55/// let json = json::obj()
56///     .set("name", name.to_json())
57///     .set("age", age.to_json())
58///     .set("active", active.to_json())
59///     .set("tags", tags.to_json());
60///
61/// let s = json.to_string();
62/// assert!(s.contains("Alice"));
63/// assert!(s.contains("30"));
64/// assert!(s.contains("true"));
65/// assert!(s.contains("admin"));
66/// ```
67pub trait ToJson {
68    /// Convert this value to a JSON value.
69    fn to_json(&self) -> JsonValue;
70}
71
72// === String implementations ===
73
74impl ToJson for String {
75    #[inline]
76    fn to_json(&self) -> JsonValue {
77        str(self)
78    }
79}
80
81impl ToJson for &str {
82    #[inline]
83    fn to_json(&self) -> JsonValue {
84        str(*self)
85    }
86}
87
88impl ToJson for std::borrow::Cow<'_, str> {
89    #[inline]
90    fn to_json(&self) -> JsonValue {
91        str(self.as_ref())
92    }
93}
94
95// === Integer implementations ===
96
97impl ToJson for i8 {
98    #[inline]
99    fn to_json(&self) -> JsonValue {
100        int(i64::from(*self))
101    }
102}
103
104impl ToJson for i16 {
105    #[inline]
106    fn to_json(&self) -> JsonValue {
107        int(i64::from(*self))
108    }
109}
110
111impl ToJson for i32 {
112    #[inline]
113    fn to_json(&self) -> JsonValue {
114        int(i64::from(*self))
115    }
116}
117
118impl ToJson for i64 {
119    #[inline]
120    fn to_json(&self) -> JsonValue {
121        int(*self)
122    }
123}
124
125impl ToJson for isize {
126    #[inline]
127    fn to_json(&self) -> JsonValue {
128        int(*self as i64)
129    }
130}
131
132impl ToJson for u8 {
133    #[inline]
134    fn to_json(&self) -> JsonValue {
135        int(i64::from(*self))
136    }
137}
138
139impl ToJson for u16 {
140    #[inline]
141    fn to_json(&self) -> JsonValue {
142        int(i64::from(*self))
143    }
144}
145
146impl ToJson for u32 {
147    #[inline]
148    fn to_json(&self) -> JsonValue {
149        int(i64::from(*self))
150    }
151}
152
153impl ToJson for u64 {
154    #[inline]
155    fn to_json(&self) -> JsonValue {
156        // Note: Values > i64::MAX will be truncated
157        int(*self as i64)
158    }
159}
160
161impl ToJson for usize {
162    #[inline]
163    fn to_json(&self) -> JsonValue {
164        int(*self as i64)
165    }
166}
167
168// === Float implementations ===
169
170impl ToJson for f32 {
171    #[inline]
172    fn to_json(&self) -> JsonValue {
173        float(f64::from(*self))
174    }
175}
176
177impl ToJson for f64 {
178    #[inline]
179    fn to_json(&self) -> JsonValue {
180        float(*self)
181    }
182}
183
184// === Boolean implementation ===
185
186impl ToJson for bool {
187    #[inline]
188    fn to_json(&self) -> JsonValue {
189        super::builder::bool(*self)
190    }
191}
192
193// === Option implementation (None becomes null) ===
194
195impl<T: ToJson> ToJson for Option<T> {
196    #[inline]
197    fn to_json(&self) -> JsonValue {
198        self.as_ref().map_or_else(null, ToJson::to_json)
199    }
200}
201
202// === Array implementations ===
203
204impl<T: ToJson> ToJson for Vec<T> {
205    #[inline]
206    fn to_json(&self) -> JsonValue {
207        let mut result = arr();
208        for item in self {
209            result = result.push(item.to_json());
210        }
211        result
212    }
213}
214
215impl<T: ToJson> ToJson for &[T] {
216    #[inline]
217    fn to_json(&self) -> JsonValue {
218        let mut result = arr();
219        for item in *self {
220            result = result.push(item.to_json());
221        }
222        result
223    }
224}
225
226// Fixed-size array implementations for common sizes
227impl<T: ToJson, const N: usize> ToJson for [T; N] {
228    #[inline]
229    fn to_json(&self) -> JsonValue {
230        let mut result = arr();
231        for item in self {
232            result = result.push(item.to_json());
233        }
234        result
235    }
236}
237
238// === JsonValue pass-through ===
239
240impl ToJson for JsonValue {
241    #[inline]
242    fn to_json(&self) -> JsonValue {
243        self.clone()
244    }
245}
246
247// === Reference implementations ===
248
249impl<T: ToJson + ?Sized> ToJson for &T {
250    #[inline]
251    fn to_json(&self) -> JsonValue {
252        (*self).to_json()
253    }
254}
255
256impl<T: ToJson + ?Sized> ToJson for &mut T {
257    #[inline]
258    fn to_json(&self) -> JsonValue {
259        (**self).to_json()
260    }
261}
262
263impl<T: ToJson + ?Sized> ToJson for Box<T> {
264    #[inline]
265    fn to_json(&self) -> JsonValue {
266        (**self).to_json()
267    }
268}
269
270impl<T: ToJson> ToJson for std::rc::Rc<T> {
271    #[inline]
272    fn to_json(&self) -> JsonValue {
273        (**self).to_json()
274    }
275}
276
277impl<T: ToJson> ToJson for std::sync::Arc<T> {
278    #[inline]
279    fn to_json(&self) -> JsonValue {
280        (**self).to_json()
281    }
282}