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