tina-core 0.0.2

Tina platform
Documentation
//! JSON 工具
use crate::app_system_error;
use crate::serde::de::DeserializeOwned;
use crate::serde::Serialize;
use crate::serde_json::value::RawValue;
use crate::serde_json::Value;
use crate::tina::data::AppResult;
use tracing::Level;

/// JSON 工具
pub struct JsonUtil;

impl JsonUtil {
    /// 转换成JSON Value
    pub fn to_json_value<T>(obj: &T) -> Value
    where
        T: Serialize,
    {
        match serde_json::to_value(obj) {
            Ok(v) => v,
            Err(err) => {
                if tracing::enabled!(Level::ERROR) {
                    tracing::error!("{}", err);
                }
                Value::Null
            }
        }
    }
    /// 转换成 JSON RawValue
    pub fn to_json_raw_value<T>(obj: &T) -> Box<RawValue>
    where
        T: Serialize,
    {
        match serde_json::value::to_raw_value(obj) {
            Ok(v) => v,
            Err(err) => {
                if tracing::enabled!(Level::ERROR) {
                    tracing::error!("{}", err);
                }
                serde_json::value::to_raw_value(&Value::Null).unwrap_or_else(|err| {
                    tracing::error!("{}", err);
                    Default::default()
                })
            }
        }
    }

    /// 转换成JSON 字符串
    pub fn to_json_string<T>(obj: &T) -> String
    where
        T: Serialize,
    {
        match serde_json::to_string(obj) {
            Ok(s) => s,
            Err(err) => {
                if tracing::enabled!(Level::ERROR) {
                    tracing::error!("{}", err);
                }
                "".to_owned()
            }
        }
    }

    /// 转换成JSON 格式化后的字符串
    pub fn to_json_string_pretty<T>(obj: &T) -> String
    where
        T: Serialize,
    {
        match serde_json::to_string_pretty(obj) {
            Ok(s) => s,
            Err(_) => "".to_owned(),
        }
    }

    /// 解析JSON字符串
    pub fn parse_json_string<T>(json: &str) -> AppResult<T>
    where
        T: Sized + DeserializeOwned,
    {
        serde_json::from_str(json).map_err(crate::app_error_from!())
    }

    /// 解析JSON Value
    pub fn parse_json_value<T>(json_value: &Value) -> AppResult<T>
    where
        T: Sized + DeserializeOwned,
    {
        T::deserialize(json_value).map_err(crate::app_error_from!())
    }

    /// 解析JSON RawValue
    pub fn parse_json_raw_value<T>(json_raw_value: &RawValue) -> AppResult<T>
    where
        T: Sized + DeserializeOwned,
    {
        serde_json::from_str(json_raw_value.get()).map_err(crate::app_error_from!())
    }

    /// 合并JSON Value
    pub fn merge_value(value1: Value, valu2: Value) -> AppResult<Value> {
        match (value1, valu2) {
            (Value::Object(mut v1), Value::Object(mut v2)) => {
                v1.append(&mut v2);
                Ok(Value::Object(v1))
            }
            (Value::Array(mut v1), Value::Array(mut v2)) => {
                v1.append(&mut v2);
                Ok(Value::Array(v1))
            }
            (v1, Value::Null) => Ok(v1),
            (Value::Null, v2) => Ok(v2),
            _ => Err(app_system_error!("only Object, Array and Null can be merged!")),
        }
    }
}

#[cfg(test)]
#[allow(unused)]
mod test {
    use crate::tina::util::json::JsonUtil;
    use serde::{Deserialize, Serialize};

    #[derive(Serialize, Deserialize)]
    struct Person {
        name: String,
        age: u8,
        phones: Vec<String>,
    }

    #[test]
    fn test() {
        // Some JSON input data as a &str. Maybe this comes from the user.
        let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

        // Parse the string of data into a Person object. This is exactly the
        // same function as the one that produced serde_json::Value above, but
        // now we are asking it for a Person as output.
        // let p: Person = serde_json::from_str(data).expect("ERR");
        let p: Person = JsonUtil::parse_json_string(data).expect("test");

        // Do things just like with any other Rust data structure.
        println!("Please call {} at the number {}", p.name, p.phones[0]);

        println!("Normal: \r\n{}", JsonUtil::to_json_string(&p));
        println!("Pretty: \r\n{}", JsonUtil::to_json_string_pretty(&p));
    }

    #[test]
    fn test_vec() {
        let vec1 = vec![11, 22, 33];
        println!("Normal: \r\n{}", JsonUtil::to_json_string(&vec1));
        println!("Pretty: \r\n{}", JsonUtil::to_json_string_pretty(&vec1));
        let vec1 = vec!["11", "22", "33"];
        println!("Normal: \r\n{}", JsonUtil::to_json_string(&vec1));
        println!("Pretty: \r\n{}", JsonUtil::to_json_string_pretty(&vec1));
    }

    #[test]
    #[ignore]
    fn test_memory() {
        loop {
            // Some JSON input data as a &str. Maybe this comes from the user.
            let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

            // Parse the string of data into a Person object. This is exactly the
            // same function as the one that produced serde_json::Value above, but
            // now we are asking it for a Person as output.
            // let p: Person = serde_json::from_str(data).expect("ERR");
            let p: Person = JsonUtil::parse_json_string(data).expect("test");
            let string = JsonUtil::to_json_string(&p);
            let string1 = JsonUtil::to_json_string_pretty(&p);

            // Do things just like with any other Rust data structure.
            // println!("Please call {} at the number {}", p.name, p.phones[0]);

            // println!("Normal: \r\n{}", Json::stringify(&p));
        }
    }
}