facet_format_json/lib.rs
1#![forbid(unsafe_code)]
2
3//! JSON parser and serializer using facet-format.
4//!
5//! This crate provides JSON support via the `FormatParser` trait.
6
7extern crate alloc;
8
9mod adapter;
10mod error;
11mod parser;
12mod raw_json;
13#[cfg(feature = "streaming")]
14mod scan_buffer;
15mod scanner;
16mod serializer;
17
18#[cfg(feature = "streaming")]
19mod streaming_adapter;
20
21pub use parser::{JsonError, JsonParser};
22pub use raw_json::RawJson;
23pub use serializer::{
24 JsonSerializeError, JsonSerializer, SerializeOptions, peek_to_string, peek_to_string_pretty,
25 peek_to_string_with_options, peek_to_writer_std, peek_to_writer_std_pretty,
26 peek_to_writer_std_with_options, to_string, to_string_pretty, to_string_with_options, to_vec,
27 to_vec_pretty, to_vec_with_options, to_writer_std, to_writer_std_pretty,
28 to_writer_std_with_options,
29};
30
31// Re-export DeserializeError for convenience
32pub use facet_format::DeserializeError;
33
34/// Deserialize a value from a JSON string into an owned type.
35///
36/// This is the recommended default for most use cases. The input does not need
37/// to outlive the result, making it suitable for deserializing from temporary
38/// buffers (e.g., HTTP request bodies).
39///
40/// Types containing `&str` fields cannot be deserialized with this function;
41/// use `String` or `Cow<str>` instead. For zero-copy deserialization into
42/// borrowed types, use [`from_str_borrowed`].
43///
44/// # Example
45///
46/// ```
47/// use facet::Facet;
48/// use facet_format_json::from_str;
49///
50/// #[derive(Facet, Debug, PartialEq)]
51/// struct Person {
52/// name: String,
53/// age: u32,
54/// }
55///
56/// let json = r#"{"name": "Alice", "age": 30}"#;
57/// let person: Person = from_str(json).unwrap();
58/// assert_eq!(person.name, "Alice");
59/// assert_eq!(person.age, 30);
60/// ```
61pub fn from_str<T>(input: &str) -> Result<T, DeserializeError<JsonError>>
62where
63 T: facet_core::Facet<'static>,
64{
65 from_slice(input.as_bytes())
66}
67
68/// Deserialize a value from JSON bytes into an owned type.
69///
70/// This is the recommended default for most use cases. The input does not need
71/// to outlive the result, making it suitable for deserializing from temporary
72/// buffers (e.g., HTTP request bodies).
73///
74/// Types containing `&str` fields cannot be deserialized with this function;
75/// use `String` or `Cow<str>` instead. For zero-copy deserialization into
76/// borrowed types, use [`from_slice_borrowed`].
77///
78/// # Example
79///
80/// ```
81/// use facet::Facet;
82/// use facet_format_json::from_slice;
83///
84/// #[derive(Facet, Debug, PartialEq)]
85/// struct Point {
86/// x: i32,
87/// y: i32,
88/// }
89///
90/// let json = br#"{"x": 10, "y": 20}"#;
91/// let point: Point = from_slice(json).unwrap();
92/// assert_eq!(point.x, 10);
93/// assert_eq!(point.y, 20);
94/// ```
95pub fn from_slice<T>(input: &[u8]) -> Result<T, DeserializeError<JsonError>>
96where
97 T: facet_core::Facet<'static>,
98{
99 use facet_format::FormatDeserializer;
100 let parser = JsonParser::new(input);
101 let mut de = FormatDeserializer::new_owned(parser);
102 de.deserialize_root()
103}
104
105/// Deserialize a value from a JSON string, allowing zero-copy borrowing.
106///
107/// This variant requires the input to outlive the result (`'input: 'facet`),
108/// enabling zero-copy deserialization of string fields as `&str` or `Cow<str>`.
109///
110/// Use this when you need maximum performance and can guarantee the input
111/// buffer outlives the deserialized value. For most use cases, prefer
112/// [`from_str`] which doesn't have lifetime requirements.
113///
114/// # Example
115///
116/// ```
117/// use facet::Facet;
118/// use facet_format_json::from_str_borrowed;
119///
120/// #[derive(Facet, Debug, PartialEq)]
121/// struct Person<'a> {
122/// name: &'a str,
123/// age: u32,
124/// }
125///
126/// let json = r#"{"name": "Alice", "age": 30}"#;
127/// let person: Person = from_str_borrowed(json).unwrap();
128/// assert_eq!(person.name, "Alice");
129/// assert_eq!(person.age, 30);
130/// ```
131pub fn from_str_borrowed<'input, 'facet, T>(
132 input: &'input str,
133) -> Result<T, DeserializeError<JsonError>>
134where
135 T: facet_core::Facet<'facet>,
136 'input: 'facet,
137{
138 from_slice_borrowed(input.as_bytes())
139}
140
141/// Deserialize a value from JSON bytes, allowing zero-copy borrowing.
142///
143/// This variant requires the input to outlive the result (`'input: 'facet`),
144/// enabling zero-copy deserialization of string fields as `&str` or `Cow<str>`.
145///
146/// Use this when you need maximum performance and can guarantee the input
147/// buffer outlives the deserialized value. For most use cases, prefer
148/// [`from_slice`] which doesn't have lifetime requirements.
149///
150/// # Example
151///
152/// ```
153/// use facet::Facet;
154/// use facet_format_json::from_slice_borrowed;
155///
156/// #[derive(Facet, Debug, PartialEq)]
157/// struct Point<'a> {
158/// label: &'a str,
159/// x: i32,
160/// y: i32,
161/// }
162///
163/// let json = br#"{"label": "origin", "x": 0, "y": 0}"#;
164/// let point: Point = from_slice_borrowed(json).unwrap();
165/// assert_eq!(point.label, "origin");
166/// ```
167pub fn from_slice_borrowed<'input, 'facet, T>(
168 input: &'input [u8],
169) -> Result<T, DeserializeError<JsonError>>
170where
171 T: facet_core::Facet<'facet>,
172 'input: 'facet,
173{
174 use facet_format::FormatDeserializer;
175 let parser = JsonParser::new(input);
176 let mut de = FormatDeserializer::new(parser);
177 de.deserialize_root()
178}
179
180#[cfg(feature = "streaming")]
181mod streaming;
182#[cfg(feature = "futures-io")]
183pub use streaming::from_async_reader_futures;
184#[cfg(feature = "tokio")]
185pub use streaming::from_async_reader_tokio;
186#[cfg(feature = "streaming")]
187pub use streaming::from_reader;