serde_mappable_seq/lib.rs
1//! [![license-badge][]][license] [![docs-badge][]][docs] [![rust badge]][rust link]
2//!
3//! # serde-mappable-seq
4//!
5//! An unofficial third-party crate to deserialize sequences of keyed structs
6//! into HashMaps or BTreeMaps and vice versa.
7//!
8//! Sometimes APIs will provide a list of instances of a resource in a sequence,
9//! such as a list of users. Imagine this JSON payload:
10//!
11//! ```json
12//! {
13//! "data": {
14//! "users": [
15//! {
16//! "id": 1,
17//! "name": "foo"
18//! }
19//! ]
20//! },
21//! "links": {}
22//! }
23//! ```
24//!
25//! If you want to get something by ID, you're going to either need to
26//! post-process it manually (slightly annoying) or loop through to find the user
27//! with the ID (slightly costly).
28//!
29//! `serde-mappable-seq` makes turning a sequence of a resource into a keyed
30//! map easy.
31//!
32//! ### Installation
33//!
34//! This library requires at least Rust 1.31.0.
35//!
36//! Add this to your `Cargo.toml`:
37//!
38//! ```toml
39//! [dependencies]
40//! serde-mappable-seq = "0.1"
41//! ```
42//!
43//! ### Examples
44//!
45//! Deserialize a struct containing a sequence of 2 users into a HashMap, keyed
46//! by their IDs:
47//!
48//! ```
49//! use serde_derive::{Deserialize, Serialize};
50//! use serde_mappable_seq::Key;
51//! use std::collections::HashMap;
52//!
53//! #[derive(Deserialize, Serialize)]
54//! struct User {
55//! id: u64,
56//! name: String,
57//! }
58//!
59//! impl Key<'_, u64> for User {
60//! fn key(&self) -> u64 {
61//! self.id
62//! }
63//! }
64//!
65//! #[derive(Deserialize, Serialize)]
66//! struct Response {
67//! #[serde(with = "serde_mappable_seq")]
68//! users: HashMap<u64, User>,
69//! }
70//!
71//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
72//! let input = r#"{
73//! "users": [
74//! {
75//! "id": 1,
76//! "name": "foo"
77//! }
78//! ]
79//! }"#;
80//!
81//! let response = serde_json::from_str::<Response>(input)?;
82//! assert_eq!("foo", response.users.get(&1).unwrap().name);
83//!
84//! // Now serialize it back and make sure it's the same as the original input.
85//! assert_eq!(input, serde_json::to_string_pretty(&response)?);
86//! # Ok(()) }
87//! ```
88//!
89//! Serializing the instance of the response struct in the above example will
90//! net back the original input.
91//!
92//! ### License
93//!
94//! ISC.
95//!
96//! [docs]: https://docs.rs/serde-mappable-seq
97//! [docs-badge]: https://img.shields.io/badge/docs-online-5023dd.svg?style=flat-square
98//! [license]: https://opensource.org/licenses/ISC
99//! [license-badge]: https://img.shields.io/badge/license-ISC-blue.svg?style=flat-square
100//! [rust badge]: https://img.shields.io/badge/rust-1.31+-93450a.svg?style=flat-square
101//! [rust link]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
102
103pub mod btreemap;
104pub mod hashmap;
105
106pub use self::hashmap::{deserialize, serialize};
107
108use serde::{Deserialize, Serialize};
109use std::hash::Hash;
110
111/// The key to a keyed resource.
112///
113/// Implement this on the type of the value of a map to extract the key from it.
114///
115/// # Examples
116///
117/// If you have a User resource, then it'll have an ID of some sort. For
118/// example, return the integer ID of a User struct:
119///
120/// ```
121/// use serde_derive::{Deserialize, Serialize};
122/// use serde_mappable_seq::Key;
123///
124/// struct User {
125/// id: u64,
126/// email: String,
127/// name: String,
128/// }
129///
130/// impl Key<'_, u64> for User {
131/// fn key(&self) -> u64 {
132/// self.id
133/// }
134/// }
135/// ```
136pub trait Key<'a, T: Deserialize<'a> + Eq + Hash + Serialize> {
137 /// The method to extract an owned key from the type.
138 fn key(&self) -> T;
139}