json_api/doc/
mod.rs

1//! Components of a JSON API document.
2
3mod convert;
4mod ident;
5mod link;
6mod object;
7mod relationship;
8mod specification;
9
10mod error;
11
12use std::iter::FromIterator;
13
14use serde::de::DeserializeOwned;
15use serde::ser::Serialize;
16
17use error::Error;
18use query::Query;
19use sealed::Sealed;
20use value::{Key, Map, Set, Value};
21use view::Render;
22
23pub use self::convert::*;
24pub use self::error::{ErrorObject, ErrorSource};
25pub use self::ident::Identifier;
26pub use self::link::Link;
27pub use self::object::{NewObject, Object};
28pub use self::relationship::Relationship;
29pub use self::specification::{JsonApi, Version};
30
31/// A marker trait used to indicate that a type can be the primary data for a
32/// document.
33pub trait PrimaryData: DeserializeOwned + Sealed + Serialize {
34    #[doc(hidden)]
35    fn flatten(self, &Set<Object>) -> Value;
36}
37
38/// Represents a compound JSON API document.
39///
40/// For more information, check out the *[document structure]* section of the JSON API
41/// specification.
42///
43/// [document structure]: https://goo.gl/CXTNmt
44#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
45#[serde(bound = "T: PrimaryData", untagged)]
46pub enum Document<T: PrimaryData> {
47    /// Does not contain errors.
48    Ok {
49        /// The primary data of the document. For more information, check out the
50        /// *[top level]* section of the JSON API specification.
51        ///
52        /// [top level]: https://goo.gl/fQdYgo
53        data: Data<T>,
54
55        /// Included resources, resolved from the `include` query parameter of a client
56        /// request.
57        #[serde(default, skip_serializing_if = "Set::is_empty")]
58        included: Set<Object>,
59
60        /// Information about this implementation of the specification that the
61        /// document was created with. For more information, check out the *[JSON API
62        /// object]* section of the JSON API specification.
63        ///
64        /// [JSON API object]: https://goo.gl/hZUcEt
65        #[serde(default)]
66        jsonapi: JsonApi,
67
68        /// Contains relevant links. If this value of this field is empty, it will not be
69        /// serialized. For more information, check out the *[links]* section of the JSON
70        /// API specification.
71        ///
72        /// [links]: https://goo.gl/E4E6Vt
73        #[serde(default, skip_serializing_if = "Map::is_empty")]
74        links: Map<Key, Link>,
75
76        /// Non-standard meta information. If this value of this field is empty, it will
77        /// not be serialized. For more information, check out the *[meta
78        /// information]* section of the JSON API specification.
79        ///
80        /// [meta information]: https://goo.gl/LyrGF8
81        #[serde(default, skip_serializing_if = "Map::is_empty")]
82        meta: Map,
83    },
84
85    /// Contains 1 or more error(s).
86    Err {
87        errors: Vec<ErrorObject>,
88
89        #[serde(default)]
90        jsonapi: JsonApi,
91
92        #[serde(default, skip_serializing_if = "Map::is_empty")]
93        links: Map<Key, Link>,
94
95        #[serde(default, skip_serializing_if = "Map::is_empty")]
96        meta: Map,
97    },
98}
99
100impl<T: PrimaryData> Document<T> {
101    /// Returns `true` if the document does not contain any errors.
102    pub fn is_ok(&self) -> bool {
103        match *self {
104            Document::Ok { .. } => true,
105            Document::Err { .. } => false,
106        }
107    }
108
109    /// Returns `true` if the document contains 1 or more error(s).
110    pub fn is_err(&self) -> bool {
111        match *self {
112            Document::Ok { .. } => true,
113            Document::Err { .. } => false,
114        }
115    }
116}
117
118impl<T: PrimaryData> Render<T> for Document<T> {
119    fn render(self, _: Option<&Query>) -> Result<Document<T>, Error> {
120        Ok(self)
121    }
122}
123
124/// Describes the data of a document or resource linkage.
125///
126/// For more information, check out the *[top level]* section of the JSON API
127/// specification.
128///
129/// [top level]: https://goo.gl/fQdYgo
130#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
131#[serde(bound = "T: PrimaryData", untagged)]
132pub enum Data<T: PrimaryData> {
133    /// A collection of `T`. Used for requests that target resource collections.
134    Collection(Vec<T>),
135
136    /// An optional `T`. Used for requests that target single resources.
137    Member(Box<Option<T>>),
138}
139
140impl<T: PrimaryData> From<Option<T>> for Data<T> {
141    fn from(value: Option<T>) -> Self {
142        Data::Member(Box::new(value))
143    }
144}
145
146impl<T: PrimaryData> From<Vec<T>> for Data<T> {
147    fn from(value: Vec<T>) -> Self {
148        Data::Collection(value)
149    }
150}
151
152impl<T: PrimaryData> From<T> for Data<T> {
153    fn from(value: T) -> Self {
154        Data::Member(Box::new(Some(value)))
155    }
156}
157
158impl<T: PrimaryData> FromIterator<T> for Data<T> {
159    fn from_iter<I>(iter: I) -> Self
160    where
161        I: IntoIterator<Item = T>,
162    {
163        Data::Collection(Vec::from_iter(iter))
164    }
165}