googletest_json_serde/matchers/
json_matcher.rs1use crate::matchers::__internal_unstable_do_not_depend_on_these::JsonPredicateMatcher;
4
5pub fn is_null() -> JsonPredicateMatcher {
7 JsonPredicateMatcher::new(|v| v.is_null(), "JSON null", "which is not JSON null")
8}
9
10pub fn is_not_null() -> JsonPredicateMatcher {
12 JsonPredicateMatcher::new(|v| !v.is_null(), "not JSON null", "which is JSON null")
13}
14
15#[deprecated(since = "0.2.2", note = "Use `is_not_null` instead")]
17pub fn any_value() -> JsonPredicateMatcher {
18 JsonPredicateMatcher::new(
19 |v| !v.is_null(),
20 "any JSON value",
21 "which is not any JSON value",
22 )
23}
24
25pub fn is_string() -> JsonPredicateMatcher {
27 JsonPredicateMatcher::new(
28 |v| v.is_string(),
29 "a JSON string",
30 "which is not a JSON string",
31 )
32}
33
34pub fn is_number() -> JsonPredicateMatcher {
36 JsonPredicateMatcher::new(
37 |v| v.is_number(),
38 "a JSON number",
39 "which is not a JSON number",
40 )
41}
42
43pub fn is_boolean() -> JsonPredicateMatcher {
45 JsonPredicateMatcher::new(
46 |v| v.is_boolean(),
47 "a JSON boolean",
48 "which is not a JSON boolean",
49 )
50}
51
52pub fn is_array() -> JsonPredicateMatcher {
54 JsonPredicateMatcher::new(
55 |v| v.is_array(),
56 "a JSON array",
57 "which is not a JSON array",
58 )
59}
60
61pub fn is_object() -> JsonPredicateMatcher {
63 JsonPredicateMatcher::new(
64 |v| v.is_object(),
65 "a JSON object",
66 "which is not a JSON object",
67 )
68}
69
70#[doc(hidden)]
71pub mod internal {
72 use googletest::description::Description;
73 use googletest::matcher::MatcherResult::{Match, NoMatch};
74 use googletest::matcher::{Matcher, MatcherBase, MatcherResult};
75 use serde_json::Value;
76
77 #[derive(MatcherBase)]
78 pub struct JsonPredicateMatcher {
79 predicate: fn(&Value) -> bool,
80 positive_description: &'static str,
81 negative_description: &'static str,
82 }
83 impl JsonMatcher for JsonPredicateMatcher {}
84
85 impl JsonPredicateMatcher {
86 pub fn new(
87 predicate: fn(&Value) -> bool,
88 positive_description: &'static str,
89 negative_description: &'static str,
90 ) -> Self {
91 Self {
92 predicate,
93 positive_description,
94 negative_description,
95 }
96 }
97 }
98 impl Matcher<&Value> for JsonPredicateMatcher {
99 fn matches(&self, actual: &Value) -> MatcherResult {
100 match (self.predicate)(actual) {
101 true => Match,
102 false => NoMatch,
103 }
104 }
105
106 fn describe(&self, matcher_result: MatcherResult) -> Description {
107 match matcher_result {
108 Match => self.positive_description.into(),
109 NoMatch => self.negative_description.into(),
110 }
111 }
112 fn explain_match(&self, actual: &Value) -> Description {
113 let kind = match actual {
114 Value::String(_) => "a JSON string",
115 Value::Number(_) => "a JSON number",
116 Value::Bool(_) => "a JSON boolean",
117 Value::Null => "a JSON null",
118 Value::Array(_) => "a JSON array",
119 Value::Object(_) => "a JSON object",
120 };
121 Description::new().text(format!("which is {kind}"))
122 }
123 }
124
125 pub trait JsonMatcher: for<'a> Matcher<&'a Value> {}
127
128 pub trait IntoJsonMatcher<T> {
130 fn into_json_matcher(self) -> Box<dyn for<'a> Matcher<&'a Value>>;
131 }
132
133 impl<J> IntoJsonMatcher<()> for J
134 where
135 J: JsonMatcher + 'static,
136 {
137 fn into_json_matcher(self) -> Box<dyn for<'a> Matcher<&'a Value>> {
138 Box::new(self)
139 }
140 }
141}