Crates.io | serde_single_or_vec |
lib.rs | serde_single_or_vec |
version | 1.0.1 |
source | src |
created_at | 2020-11-13 13:23:36.399799 |
updated_at | 2020-11-16 08:57:04.602803 |
description | Type which can be deserialized from either a sequence or a single value |
homepage | |
repository | https://github.com/mettke/serde_single_or_vec |
max_upload_size | |
id | 311934 |
size | 35,211 |
This crate provides the SingleOrVec
Type which allows
parsing either a single type T or a vector of type T using serde.
This is required when a server either returns an array
if there are multiple values or one value if there is only one.
#[derive(Deserialize, Serialize)]
struct Response {
single: SingleOrVec<'static, u8>,
multiple: SingleOrVec<'static, u8>,
}
let json = r#"{
"single": 0,
"multiple": [
0,
1,
2
]
}"#;
let res: Response = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string_pretty(&res).unwrap());
By default the SingleOrVec
Type deserializes its content either
to a single value or an array if it contains multiple values. To change
this behaviour, its possible to define the output format.
#[derive(Deserialize, Serialize)]
struct Response {
single: SingleOrVec<'static, u8>,
multiple: SingleOrVec<'static, u8>,
}
let json = "[0]";
let res: SingleOrVec<'_, u8, PreferSingle> = serde_json::from_str(json).unwrap();
assert_eq!("0", &serde_json::to_string(&res).unwrap());
let res: SingleOrVec<'_, u8, AlwaysVector> = serde_json::from_str(json).unwrap();
assert_eq!("[0]", &serde_json::to_string(&res).unwrap());
The default Backend is a Vec<T>
and thus always results in an allocation.
An alternativ is to use a Cow<'_, T>
as backend which only requires an allocation
for a single value.
Note that this is only valid when using or serializing this value, deserialisation always allocates due to serde#1852
let json = "[0,1,2]";
let res: SingleOrVec<'_, u8, PreferSingle, Cow<'_, [u8]>> = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string(&res).unwrap());
Its also possible to implement Custom Storage Backends by using the Storage
Trait.
use arrayvec::ArrayVec;
struct ArrayVecStorage {}
impl<T> Storage<'_, T> for ArrayVecStorage {
type Backing = ArrayVec<[T; 4]>;
fn single(ty: T) -> Self::Backing {
let mut vec = ArrayVec::new();
vec.push(ty);
vec
}
fn get_first_with_len(b: &Self::Backing) -> Option<(&T, usize)> {
b.split_first().map(|(t, r)| (t, r.len()))
}
}
let json = "[0,1,2]";
let res: SingleOrVec<'_, u8, PreferSingle, ArrayVecStorage> = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string(&res).unwrap());
let json = "0";
let res: SingleOrVec<'_, u8, PreferSingle, ArrayVecStorage> = serde_json::from_str(json).unwrap();
assert_eq!(json, &serde_json::to_string(&res).unwrap());
no_std
It is possible to use this crate with no_std
, however, like serde, either std
or
alloc
is required.
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
License: MIT OR Apache-2.0