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
//! Json Value Description is a package for outputting a description of unstructured data parsed by Serde Json into a Value.
#![forbid(unsafe_code)]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use serde_json::{Value};

fn json_type(val: &Value) -> &'static str {
    match val {
        Value::Object(_data) => { "\"Object\"" },
        Value::Bool(_) => { "\"Bool\"" },
        Value::Number(_) => { "\"Number\"" },
        Value::String(_) => { "\"String\"" },
        Value::Array(_) => { "\"Array\"" },
        Value::Null => { "\"Null\"" },
    }
}

/// Attempts to describe the schema of a json value that is provided.
pub fn json_object_description(json_value: &Value) -> String {
    if let Some(object) = json_value.as_object() {
        let mut obj_key = vec![];
        for (key, value) in object {
            let field_description = if value.is_object() {
                json_object_description(value)
            } else {
                json_type(value).into()
            };
            obj_key.push(format!("\"{}\": {}", key, field_description));
        };
        format!("{{ {} }}", obj_key.join(", "))
    } else {
        json_type(json_value).into()
    }
}

#[cfg(test)]
mod tests {
    use crate::json_object_description;

    use serde_json::{Value};

    const EMPTY: &'static str = r#"{}"#;
    const ARR: &'static str = r#"[]"#;
    const COMPLEX: &'static str = r#"{ "hello": "world", "count": 42, "question": true, "nest": { "one": { "two": "three", "example": null } }}"#;

    #[test]
    fn empty() {
        let data: Value = serde_json::from_str(EMPTY).unwrap();
        assert_eq!(self::json_object_description(&data), "{  }");
    }

    #[test]
    fn array() {
        let data: Value = serde_json::from_str(ARR).unwrap();
        assert_eq!(self::json_object_description(&data), "\"Array\"");
    }

    #[test]
    fn complex() {
        let data: Value = serde_json::from_str(COMPLEX).unwrap();
        assert_eq!(self::json_object_description(&data), "{ \"count\": \"Number\", \"hello\": \"String\", \"nest\": { \"one\": { \"example\": \"Null\", \"two\": \"String\" } }, \"question\": \"Bool\" }");
    }
}