Expand description
Query strings and form data (application/x-www-form-urlencoded) for
deser.
use deser::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
struct Search {
q: String,
page: Option<u32>,
#[deser(default)]
tags: Vec<String>,
}
let search: Search =
deser_urlencoded::from_str("q=rust+serde&tags=a&tags=b").unwrap();
assert_eq!(search.q, "rust serde");
assert_eq!(search.page, None);
assert_eq!(search.tags, ["a", "b"]);
let query = deser_urlencoded::to_string(&search).unwrap();
assert_eq!(query, "q=rust+serde&tags=a&tags=b");§Data Model
Everything in a query string is text, the type of a value is only known to the type it’s deserialized into. Keys and values are therefore passed on as lexical atoms which are parsed by the types they are delivered to: numbers parse them, strings take them as they are. Lexical atoms are retained when values are buffered, so flattened structs and internally tagged and untagged enums work as well:
use deser::Deserialize;
#[derive(Debug, Deserialize, PartialEq)]
struct Paginate {
limit: u32,
offset: u32,
}
#[derive(Debug, Deserialize, PartialEq)]
#[deser(tag = "type", rename_all = "lowercase")]
enum Query {
Users {
active: bool,
#[deser(flatten)]
paginate: Paginate,
},
}
let query: Query = deser_urlencoded::from_str(
"limit=10&offset=20&active=yes&type=users",
)
.unwrap();
assert_eq!(
query,
Query::Users {
active: true,
paginate: Paginate { limit: 10, offset: 20 },
}
);The input is a map whose keys can repeat (a multimap). Keys can be
nested (see Nesting):
| query string | deser |
|---|---|
a=1 | {"a": "1"} |
a=1&a=2 | {"a": "1", "a": "2"} (a repeated key) |
a[]=1&a[]=2 | {"a": ["1", "2"]} |
a[0]=1&a[1]=2 | {"a": ["1", "2"]} |
a[1]=1&a[3]=2 | {"a": {"1": "1", "3": "2"}} |
a[b]=1&a[c][]=2 | {"a": {"b": "1", "c": ["2"]}} |
a[0][b]=1&a[1][b]=2 | {"a": [{"b": "1"}, {"b": "2"}]} |
Fields and map values that are collections (like Vec<T> or
HashSet<T>) collect the values of all occurrences of their key, also
if other keys are between them. A key given once is a collection of one
value and a missing key an empty collection. Types that expect a single
value receive the last one unless the Context has
another DuplicateKeys policy:
use deser::de::DuplicateKeys;
use deser::Context;
#[derive(deser::Deserialize)]
struct Query {
page: u32,
}
let query: Query = deser_urlencoded::from_str("page=1&page=2").unwrap();
assert_eq!(query.page, 2);
let strict = deser_urlencoded::DeserializerConfig::builder()
.context(Context::with(DuplicateKeys::Error))
.build();
assert!(strict.from_str::<Query>("page=1&page=2").is_err());a[]=1 is always a sequence. Indexes that start at 0 and have no
gaps are sequences, other indexes are map keys.
#[derive(deser::Deserialize, Debug, PartialEq)]
struct Filter {
tag: Vec<String>,
page: u32,
user: Vec<String>,
}
assert_eq!(
deser_urlencoded::from_str::<Filter>("tag=a&page=2&tag=b").unwrap(),
Filter { tag: vec!["a".into(), "b".into()], page: 2, user: vec![] },
);The URL standard makes no difference between a and a=, both are the
empty value. Empty values are None for optionals if the type does not
accept them (page= is None for an Option<u32> and Some("") for an
Option<String>). Booleans accept true, yes, on and 1 and
false, no, off and 0 (HTML checkboxes send on). Flags which
are switched on by giving their key (like ?recursive) use the
Flag adapter:
use deser::adapters::Flag;
#[derive(deser::Deserialize)]
struct Tree {
#[deser(as = Flag)]
recursive: bool,
}
assert!(
deser_urlencoded::from_str::<Tree>("recursive").unwrap().recursive
);
assert!(
deser_urlencoded::from_str::<Tree>("recursive=").unwrap().recursive
);
assert!(
!deser_urlencoded::from_str::<Tree>("recursive=0").unwrap().recursive
);
assert!(!deser_urlencoded::from_str::<Tree>("").unwrap().recursive);Keys and values are percent-decoded (+ is a space) before the keys are
split, so a%5B%5D=1 (as sent by browsers) is the same as a[]=1.
Values which are not UTF-8 after decoding are passed on as bytes. A
leading ? is ignored. Keys which do not follow the syntax of the
nesting (like a[b) are taken as they are. A key that has a value and
nested keys (a=1&a[b]=2) is an error.
Serializing works the other way around (see SerializerConfig), how
sequences are written can be configured (see ArrayFormat).
§Streams
Form data is read from a Read with from_reader
and written to a Write with to_writer. The
configurations also create readers and writers of
deser::io (DeserializerConfig::reader and
SerializerConfig::writer), the stream serializer (Serializer)
and deserializer (StreamDeserializer) work with other kinds of IO
too (for instance async runtimes with deser-tokio). The whole stream
is read before it’s parsed.
§Features
io(enabled by default): reading and writing streams of the standard library, see streams.speedups(enabled by default): has no effect yet, it exists so that all formats have it.
Structs§
- Deserializer
- Deserializes query strings and form data.
- Deserializer
Config - Configures how query strings and form data are deserialized.
- Deserializer
Config Builder - Builds a
DeserializerConfig. - Serializer
- Serializes values into query strings.
- Serializer
Config - Configures how values are serialized to query strings.
- Serializer
Config Builder - Builds a
SerializerConfig. - Stream
Deserializer - Reads form data from a stream (see
deser::stream).
Enums§
- Array
Format - How sequences are written.
- Nesting
- How keys are nested.
Functions§
- from_
reader - Deserializes form data from a reader.
- from_
slice - Deserializes a value from a query string in a byte slice.
- from_
str - Deserializes a value from a query string.
- to_
string - Serializes a value to a query string.
- to_
writer - Serializes a value as form data to a writer.