[][src]Crate 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


#[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.


#[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<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());

Custom Storage Type

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.

License

Licensed under either of

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.

Structs

AlwaysVector

Always returns a vector on serialisation

PreferSingle

Returns a single value on serialisation if there is only one in the vector

SingleOrVec

Provides a type which can be used to parse server respsonses which either return an array or only a single value.

Traits

Format

Specifies whether Serializsation should fall back to a single value or not

Storage

Specifies the internal Storage Type of the Sequence