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 85 86 87 88 89 90 91 92
//! 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.authors.[0]")] //! first_author: String, //! #[query(".hash")] //! hash_value: u64, //! } //! //! let document = serde_json::to_string(&serde_json::json!({ //! "commit": { //! "authors": ["Kou", "Kasumi", "Masaru"], //! "date": "2020-09-10", //! }, //! "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.first_author, "Kou"); //! 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 stepping one level inside the document. //! You can combine them to go further. //! //! * `.field` for accessing a field with a name `field` of an object. //! The field name must be an alphabet followed by zero or more alphanumeric characters. //! * `.["field"]` if the field name contains special characters. //! We recommend using a raw string literal for the query parameter (`#[query(r#"..."#)]`). //! * `.[index]` for accessing an array element at position `index`. //! //! Note that mixing field access and index access at the same position of a document //! is a compile error. //! //! [`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; }