1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! A query language for Serde data model.
//!
//! This crate provides [`DeserializeQuery`] trait and [its derive macro] for defining a query.
//!
//! # Example
//!
//! ```rust
//! # use std::error::Error;
//! # fn main() -> Result<(), Box<dyn Error + 'static>> {
//! use serde_query::{DeserializeQuery, Query};
//!
//! #[derive(DeserializeQuery)]
//! struct Data {
//!     #[query(".commit.author")]
//!     commit_author: String,
//!     #[query(".hash")]
//!     hash_value: u64,
//! }
//!
//! let document = serde_json::to_string(&serde_json::json!({
//!     "commit": {
//!         "author": "pandaman64",
//!         "date": "2020/09/03",
//!     },
//!     "hash": 0xabcd,
//! }))?;
//!
//! // You can use `Query<T>` as a `Deserialize` type for any `Deserializer`
//! // and convert the result to the desired type using `From`/`Into`.
//! let data: Data = serde_json::from_str::<Query<Data>>(&document)?.into();
//!
//! assert_eq!(data.commit_author, "pandaman64");
//! assert_eq!(data.hash_value, 0xabcd);
//! # Ok(())
//! # }
//! ```
//!
//! # Deriving `DeserializeQuery`
//!
//! To declare a query, put `#[derive(DeserializeQuery)]` on your type.
//! Each field must have a `#[query(...)]` attribute for specifying
//! which part of the document should be retrieved, starting from the root.
//!
//! # `#[query(...)]` syntax
//! `serde-query` currently supports the following syntax for accessing a part of the input.
//!
//! * `.field` for accessing a field with a name `field` of an object.
//!
//! [`DeserializeQuery`]: trait.DeserializeQuery.html
//! [its derive macro]: derive.DeserializeQuery.html

/// Derive macro for [`DeserializeQuery`] trait.
///
/// Please refer to the [module-level document] for the usage.
///
/// [`DeserializeQuery`]: trait.DeserializeQuery.html
/// [module-level document]: index.html
pub use serde_query_derive::DeserializeQuery;

use serde::de::Deserialize;

/// Convenient type alias for the query type.
///
/// Please refer to the [module-level document] for details.
///
/// [module-level document]: index.html
pub type Query<'de, T> = <T as DeserializeQuery<'de>>::Query;

/// A **data structure** that can be deserialized with a query.
///
/// The [`Query`] type is automatically generated by [the proc macro],
/// and can be converted to the implementor (the type with `#[derive(DeserializeQuery)`])
/// after deserializing from the document using `Deserialize` implementation of the query type.
///
/// [`Query`]: trait.DeserializeQuery.html#associatedtype.Query
/// [the proc macro]: derive.DeserializeQuery.html
pub trait DeserializeQuery<'de>
where
    Self: From<<Self as DeserializeQuery<'de>>::Query>,
    Self::Query: Deserialize<'de>,
{
    /// The query type.
    type Query;
}