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