feattle_core/
json_reading.rs1use crate::Error;
4use serde_json::{Map, Value};
5
6#[derive(thiserror::Error, Debug)]
8pub enum FromJsonError {
9 #[error("wrong JSON kind, got {actual} and was expecting {expected}")]
10 WrongKind {
11 expected: &'static str,
12 actual: &'static str,
13 },
14 #[error("failed to parse")]
15 ParseError {
16 cause: Box<dyn Error + Send + Sync + 'static>,
17 },
18}
19
20impl FromJsonError {
21 pub fn parsing<E: Error + Send + Sync + 'static>(error: E) -> FromJsonError {
23 FromJsonError::ParseError {
24 cause: Box::new(error),
25 }
26 }
27}
28
29fn json_kind(value: &Value) -> &'static str {
30 match value {
31 Value::Null => "Null",
32 Value::Bool(_) => "Bool",
33 Value::Number(_) => "Number",
34 Value::String(_) => "String",
35 Value::Array(_) => "Array",
36 Value::Object(_) => "Object",
37 }
38}
39
40macro_rules! impl_extract_json {
41 ($fn_name:ident, $output:ty, $method:ident, $expected:expr) => {
42 #[doc = "Try to read as"]
43 #[doc = $expected]
44 pub fn $fn_name(value: &Value) -> Result<$output, FromJsonError> {
45 value.$method().ok_or_else(|| FromJsonError::WrongKind {
46 expected: $expected,
47 actual: json_kind(value),
48 })
49 }
50 };
51}
52
53impl_extract_json! { extract_array, &Vec<Value>, as_array, "Array" }
54impl_extract_json! { extract_bool, bool, as_bool, "Bool" }
55impl_extract_json! { extract_f64, f64, as_f64, "Number::f64" }
56impl_extract_json! { extract_i64, i64, as_i64, "Number::i64" }
57impl_extract_json! { extract_null, (), as_null, "Null" }
58impl_extract_json! { extract_object, &Map<String, Value>, as_object, "Object" }
59impl_extract_json! { extract_str, &str, as_str, "String" }
60impl_extract_json! { extract_u64, u64, as_u64, "Number::u64" }