# serde_single_or_vec 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. ## Example ```rust #[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()); ``` ## Format 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. ```rust #[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()); ``` ## Storage Backend The default Backend is a `Vec` 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](https://github.com/serde-rs/serde/issues/1852) ```rust 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()); ``` ## Custom Storage Type Its also possible to implement Custom Storage Backends by using the `Storage` Trait. ```rust use arrayvec::ArrayVec; struct ArrayVecStorage {} impl 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. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) * MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) at your option. ## Contribution 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