1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
//! Serde support for querystring-style strings
//!
//! This library provides serialization and deserialization of querystrings
//! with support for arbitrarily nested structures. Unlike `serde_urlencoded`,
//! which only handles flat key-value pairs, `serde_qs` supports complex nested
//! data using bracket notation (e.g., `user[name]=John&user[age]=30`).
//!
//! ## Why use `serde_qs`?
//!
//! - **Nested structure support**: Serialize/deserialize complex structs and maps
//! - **Array support**: Handle vectors and sequences with indexed notation
//! - **Framework integration**: Built-in support for Actix-web, Axum, and Warp
//! - **Compatible syntax**: Works with `qs` (JavaScript) and Rack (Ruby)
//!
//!
//! ## Basic Usage
//!
//! ```
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Address {
//! city: String,
//! postcode: String,
//! }
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct QueryParams {
//! id: u8,
//! name: String,
//! address: Address,
//! phone: u32,
//! user_ids: Vec<u8>,
//! }
//!
//! # fn main() {
//! let params = QueryParams {
//! id: 42,
//! name: "Acme".to_string(),
//! phone: 12345,
//! address: Address {
//! city: "Carrot City".to_string(),
//! postcode: "12345".to_string(),
//! },
//! user_ids: vec![1, 2, 3, 4],
//! };
//! let rec_params: QueryParams = serde_qs::from_str("\
//! name=Acme&id=42&phone=12345&address[postcode]=12345&\
//! address[city]=Carrot+City&user_ids[0]=1&user_ids[1]=2&\
//! user_ids[2]=3&user_ids[3]=4")
//! .unwrap();
//! assert_eq!(rec_params, params);
//!
//! # }
//! ```
//!
//! ## Supported Types
//!
//! `serde_qs` supports all serde-compatible types:
//!
//! - **Primitives**: strings, integers (u8-u64, i8-i64), floats (f32, f64), booleans
//! - **Strings**: UTF-8 strings (invalid UTF-8 handling configurable)
//! - **Bytes**: `Vec<u8>` and `&[u8]` for raw binary data
//! - **Collections**: `Vec<T>`, `HashMap<K, V>`, `BTreeMap<K, V>`, arrays
//! - **Options**: `Option<T>` (missing values deserialize to `None`)
//! - **Structs**: Named and tuple structs with nested fields
//! - **Enums**: Externally tagged, internally tagged, and untagged representations
//!
//! Note: Top-level types must be structs or maps. Primitives and sequences
//! cannot be deserialized at the top level. And untagged representations
//! have some limitations (see [Flatten Workaround](#flatten-workaround) section).
//!
//! ## Query-String vs Form Encoding
//!
//! By default, `serde_qs` uses **query-string encoding** which is more permissive:
//! - Spaces encoded as `+`
//! - Minimal percent-encoding (brackets remain unencoded)
//! - Example: `name=John+Doe&items[0]=apple`
//!
//! The main benefit of query-string encoding is that it allows for more compact
//! representations of nested structures, and supports square brackets in
//! key names.
//!
//! **Form encoding** (`application/x-www-form-urlencoded`) is stricter:
//! - Spaces encoded as `%20`
//! - Most special characters percent-encoded
//! - Example: `name=John%20Doe&items%5B0%5D=apple`
//!
//! Form encoding is useful for compability with HTML forms and other
//! applications that eagerly encode brackets.
//!
//! Configure encoding mode:
//! ```rust
//! use serde_qs::Config;
//!
//! // Use form encoding
//! # fn main() -> Result<(), serde_qs::Error> {
//! # let my_struct = ();
//! let config = Config::new().use_form_encoding(true);
//! let qs = config.serialize_string(&my_struct)?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Repeated keys
//!
//! When parsing a query string, repeated keys are collected into a `Vec` of values.
//!
//! - If the deserializer expects a primitive value, we'll take the **last** value
//! - If the deserializer expects a sequence, we'll deserialize all values into the sequence
//!
//! You can configure `serde_qs` to return an error when duplicate values are
//! provided for a scalar field using [`DuplicateKeyBehavior::Error`]:
//!
//! ```rust
//! use serde::Deserialize;
//! use serde_qs::{Config, DuplicateKeyBehavior};
//!
//! #[derive(Deserialize)]
//! struct Query {
//! single: String,
//! multi: Vec<String>,
//! }
//!
//! let config = Config::new().duplicate_key_behavior(DuplicateKeyBehavior::Error);
//!
//! // This fails because `single` receives multiple values
//! let result: Result<Query, _> = config.deserialize_str("single=a&single=b&multi=x&multi=y");
//! assert!(result.is_err());
//!
//! // This succeeds because `single` only has one value (multi can have many)
//! let result: Result<Query, _> = config.deserialize_str("single=a&multi=x&multi=y");
//! assert!(result.is_ok());
//! ```
//!
//! ### Array Formats
//!
//! The `array_format` option in the `Config` struct allows you to control how arrays are serialized:
//!
//! - `Indexed`: `a[0]=1&a[1]=2` (default)
//! - `EmptyIndexed`: `a[]=1&a[]=2`
//! - `Unindexed`: `a=1&a=2`
//!
//! Note that the `Indexed` format is the only one that can round-trip correctly
//! for arrays of structs or maps. Without the explicit index, we cannot
//! disambiguate which value corresponds to which key in the array.
//!
//! ## UTF-8 Handling
//!
//! By default, `serde_qs` requires valid UTF-8 in string values. If your data
//! may contain non-UTF-8 bytes, consider serializing to `Vec<u8>` instead of
//! `String`. Non-UTF-8 bytes in ignored fields will not cause errors.
//!
//! ```rust
//! # use serde::Deserialize;
//! #[derive(Deserialize)]
//! struct Data {
//! // This field can handle raw bytes
//! raw_data: Vec<u8>,
//!
//! // This field requires valid UTF-8
//! text: String,
//! }
//! ```
//!
//! ## Helpers for Common Scenarios
//!
//! The `helpers` module provides utilities for common patterns when working with
//! querystrings, particularly for handling delimited values within a single parameter.
//!
//! ### Comma-Separated Values
//!
//! Compatible with OpenAPI 3.0 `style=form` parameters:
//!
//! ```rust
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Query {
//! #[serde(with = "serde_qs::helpers::comma_separated")]
//! ids: Vec<u64>,
//! }
//!
//! # fn main() {
//! // Deserialize from comma-separated string
//! let query: Query = serde_qs::from_str("ids=1,2,3,4").unwrap();
//! assert_eq!(query.ids, vec![1, 2, 3, 4]);
//!
//! // Serialize back to comma-separated
//! let qs = serde_qs::to_string(&query).unwrap();
//! assert_eq!(qs, "ids=1,2,3,4");
//! # }
//! ```
//!
//! ### Other Delimiters
//!
//! Also supports pipe (`|`) and space delimited values:
//!
//! ```rust
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Query {
//! #[serde(with = "serde_qs::helpers::pipe_delimited")]
//! tags: Vec<String>,
//! #[serde(with = "serde_qs::helpers::space_delimited")]
//! words: Vec<String>,
//! }
//!
//! # fn main() {
//! let query: Query = serde_qs::from_str("tags=foo|bar|baz&words=hello+world").unwrap();
//! assert_eq!(query.tags, vec!["foo", "bar", "baz"]);
//! assert_eq!(query.words, vec!["hello", "world"]);
//! # }
//! ```
//!
//! ### Custom Delimiters
//!
//! For other delimiters, use the generic helper:
//!
//! ```rust
//! use serde::{Deserialize, Serialize};
//! use serde_qs::helpers::generic_delimiter::{deserialize, serialize};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Query {
//! #[serde(deserialize_with = "deserialize::<_, _, '.'>")]
//! #[serde(serialize_with = "serialize::<_, _, '.'>")]
//! versions: Vec<u8>,
//! }
//!
//! # fn main() {
//! let query: Query = serde_qs::from_str("versions=1.2.3").unwrap();
//! assert_eq!(query.versions, vec![1, 2, 3]);
//! # }
//! ```
//!
//! ## Flatten/untagged workaround
//!
//! A current [known limitation](https://github.com/serde-rs/serde/issues/1183)
//! in `serde` is deserializing `#[serde(flatten)]` structs for formats which
//! are not self-describing. This includes query strings: `12` can be an integer
//! or a string, for example.
//!
//! A similar issue exists for `#[serde(untagged)]` enums, and internally-tagged enums.
//! The default behavior using derive macros uses content buffers which defers to
//! `deserialize_any` for deserializing the inner type. This means that any string
//! parsing that should have happened in the deserializer will not happen,
//! and must be done explicitly by the user.
//!
//! We suggest the following workaround:
//!
//! ```
//! use serde::{Deserialize, Serialize};
//! use serde_with::{serde_as, DisplayFromStr};
//!
//! #[derive(Deserialize, Serialize, Debug, PartialEq)]
//! struct Query {
//! a: u8,
//! #[serde(flatten)]
//! common: CommonParams,
//! }
//!
//! #[serde_as]
//! #[derive(Deserialize, Serialize, Debug, PartialEq)]
//! struct CommonParams {
//! #[serde_as(as = "DisplayFromStr")]
//! limit: u64,
//! #[serde_as(as = "DisplayFromStr")]
//! offset: u64,
//! #[serde_as(as = "DisplayFromStr")]
//! remaining: bool,
//! }
//!
//! let params = "a=1&limit=100&offset=50&remaining=true";
//! let query = Query { a: 1, common: CommonParams { limit: 100, offset: 50, remaining: true } };
//! let rec_query: Result<Query, _> = serde_qs::from_str(params);
//! assert_eq!(rec_query.unwrap(), query);
//! ```
//!
//! ## Use with `actix_web` extractors
//!
//! The `actix4` or `actix3` features enable the use of `serde_qs::actix::QsQuery`, which
//! is a direct substitute for the `actix_web::Query` and can be used as an extractor:
//!
//! ```ignore
//! fn index(info: QsQuery<Info>) -> Result<String> {
//! Ok(format!("Welcome {}!", info.username))
//! }
//! ```
//!
//! Support for `actix-web 4.0` is available via the `actix4` feature.
//! Support for `actix-web 3.0` is available via the `actix3` feature.
//!
//! ## Use with `warp` filters
//!
//! The `warp` feature enables the use of `serde_qs::warp::query()`, which
//! is a substitute for the `warp::query::query()` filter and can be used like this:
//!
//! ```ignore
//! serde_qs::warp::query(Config::default())
//! .and_then(|info| async move {
//! Ok::<_, Rejection>(format!("Welcome {}!", info.username))
//! })
//! .recover(serde_qs::warp::recover_fn);
//! ```
//!
compile_error!;
compile_error!;
pub use ;
pub use QsDeserializer as Deserializer;
pub use ;
pub use Error;
pub use ;
pub use crateindexmap as map;
pub use cratebtree_map as map;