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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! A easy and declarative way to test JSON input in Rust.
//!
//! [assert_json!] is a Rust macro heavily inspired by [serde_json::json!] macro.
//! Instead of creating a JSON value from a JSON literal, [assert_json!] makes sure
//! the JSON input conforms to the validation rules specified.
//!
//! [assert_json!] also output beautiful error message when a validation error occurs.
//!
//! ```
//! # use assert_json::assert_json;
//! # use assert_json::validators;
//! #
//! #[test]
//! fn test_json_ok() {
//! let json = r#"
//! {
//! "status": "success",
//! "result": {
//! "id": 5,
//! "name": "charlesvdv"
//! }
//! }
//! "#;
//!
//! let name = "charlesvdv";
//!
//! assert_json!(json, {
//! "status": "success",
//! "result": {
//! "id": validators::u64(|&v| if v > 0 { Ok(())} else { Err(String::from("id should be greater than 0")) }),
//! "name": name,
//! }
//! }
//! );
//! }
//! ```
/// A JSON-value. Used by the [Validator] trait.
pub type Value = Value;
/// Validation error
/// Abstract the validation action for [assert_json!] macro.
///
/// Any custom validation rule can be easily use in the macro
/// by implementing the [Validator::validate] method.
///
/// ```
/// use assert_json::{assert_json, Error, Validator, Value};
///
/// fn optional_string(expected: Option<String>) -> impl Validator {
/// OptionalStringValidator { expected }
/// }
///
/// /// Matches a null JSON value if expected is None, else check if the strings
/// /// are equals
/// struct OptionalStringValidator {
/// expected: Option<String>,
/// }
///
/// impl Validator for OptionalStringValidator {
/// fn validate<'a>(&self, value: &'a Value) -> Result<(), Error<'a>> {
/// if let Some(expected_str) = &self.expected {
/// let string_value = value
/// .as_str()
/// .ok_or_else(|| Error::InvalidType(value, String::from("string")))?;
///
/// if expected_str == string_value {
/// Ok(())
/// } else {
/// Err(Error::InvalidValue(value, expected_str.clone()))
/// }
/// } else {
/// value.as_null()
/// .ok_or_else(|| Error::InvalidType(value, String::from("null")))
/// }
/// }
/// }
///
/// let json = r#"
/// {
/// "key": "value",
/// "none": null
/// }
/// "#;
/// assert_json!(json, {
/// "key": optional_string(Some(String::from("value"))),
/// "none": optional_string(None),
/// });
/// ```
/// Custom validators for different JSON types