Skip to main content

pistonite_cu/parse/
json_impl.rs

1/// `serde` JSON integration via the `serde_json` crate
2///
3/// Since `serde` derives requires linking with `serde` crate,
4/// you have to add it to your `Cargo.toml`:
5/// ```toml
6/// [dependencies]
7/// serde = "1"
8/// ```
9///
10/// ```rust
11/// # use pistonite_cu as cu;
12/// use cu::pre::*; // with `serde` feature, Serialize and Deserialize are
13///                 // part of the prelude
14///
15/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
16/// struct FooBar {
17///     foo: String,
18/// }
19///
20/// # fn main() -> cu::Result<()> {
21/// // the json macro and json module will also be part of the prelude
22/// let value1 = json!({"foo":"bar"});
23/// let value2: FooBar = json::from_value(value1.clone())?;
24/// assert_eq!(value2.foo, "bar");
25///
26/// let value3: FooBar = json::parse(r#"{ "foo": "bar" }"#)?;
27/// assert_eq!(value2, value3);
28///
29/// # Ok(()) }
30/// ```
31pub mod json {
32    use crate::{Context, Parse};
33    #[cfg(feature = "parse-impl")]
34    pub use ::serde_json::{de, error, map, ser, value};
35    use serde::{Deserialize, Serialize};
36    pub use serde_json::{Map, Number, Value};
37
38    /// JSON parse delegate. See [`json`](module@crate::json)
39    pub struct Json<T>(std::marker::PhantomData<T>);
40    impl<T: for<'a> Deserialize<'a>> Parse for Json<T> {
41        type Output = T;
42
43        fn parse_borrowed(x: &str) -> crate::Result<Self::Output> {
44            parse(x)
45        }
46
47        fn parse_read(x: impl std::io::Read) -> crate::Result<Self::Output> {
48            serde_json::from_reader(x).with_context(|| {
49                format!(
50                    "failed to parse input as json into {}",
51                    std::any::type_name::<T>()
52                )
53            })
54        }
55    }
56
57    /// Parse value from a JSON `&str`
58    #[inline(always)]
59    pub fn parse<'a, T: Deserialize<'a>>(x: &'a str) -> crate::Result<T> {
60        serde_json::from_str(x).with_context(|| {
61            format!(
62                "failed to parse input as json into {}",
63                std::any::type_name::<T>()
64            )
65        })
66    }
67
68    /// Parse value from a reader that yields JSON
69    #[inline(always)]
70    pub fn read<T: for<'a> Deserialize<'a>>(x: impl std::io::Read) -> crate::Result<T> {
71        Json::<T>::parse_read(x)
72    }
73
74    /// Parse value from an async reader that yields JSON
75    #[cfg(feature = "coroutine")]
76    pub async fn co_read<T: for<'a> Deserialize<'a>>(
77        x: impl tokio::io::AsyncRead + Unpin,
78    ) -> crate::Result<T> {
79        crate::co_read::<Json<T>>(x).await
80    }
81
82    /// Convert a JSON value into T
83    pub fn from_value<T: for<'a> Deserialize<'a>>(x: Value) -> crate::Result<T> {
84        use crate::Context;
85        crate::check!(
86            serde_json::from_value(x),
87            "failed to convert json value to {}",
88            std::any::type_name::<T>()
89        )
90    }
91
92    /// Convert a T into a JSON value
93    pub fn to_value<T: ?Sized + Serialize>(x: &T) -> crate::Result<Value> {
94        use crate::Context;
95        crate::check!(
96            serde_json::to_value(x),
97            "failed to convert {} to json value",
98            std::any::type_name::<T>()
99        )
100    }
101
102    /// Convert the value to a JSON string
103    pub fn stringify<T: ?Sized + Serialize>(x: &T) -> crate::Result<String> {
104        use crate::Context;
105        crate::check!(
106            serde_json::to_string(x),
107            "failed to serialize {} to json",
108            std::any::type_name::<T>()
109        )
110    }
111
112    /// Convert the value to a pretty-formatted JSON string
113    pub fn stringify_pretty<T: ?Sized + Serialize>(x: &T) -> crate::Result<String> {
114        use crate::Context;
115        crate::check!(
116            serde_json::to_string_pretty(x),
117            "failed to serialize {} to json",
118            std::any::type_name::<T>()
119        )
120    }
121
122    /// Serialize the value into JSON and write into the writer
123    pub fn write<T: ?Sized + Serialize>(w: impl std::io::Write, x: &T) -> crate::Result<()> {
124        use crate::Context;
125        crate::check!(
126            serde_json::to_writer(w, x),
127            "failed to write serialized {} as json",
128            std::any::type_name::<T>()
129        )
130    }
131
132    /// Serialize the value into pretty-formatted JSON and write into the writer
133    pub fn write_pretty<T: ?Sized + Serialize>(w: impl std::io::Write, x: &T) -> crate::Result<()> {
134        use crate::Context;
135        crate::check!(
136            serde_json::to_writer_pretty(w, x),
137            "failed to write serialized {} as json",
138            std::any::type_name::<T>()
139        )
140    }
141}
142#[cfg_attr(any(docsrs, feature = "nightly"), doc(cfg(feature = "json")))]
143pub use serde_json::json;