tina-core 0.0.2

Tina platform
Documentation
//! JSON 工具
use heck::{ToLowerCamelCase, ToSnakeCase, ToUpperCamelCase};
use serde::de::DeserializeOwned;
use serde::Serialize;
use serde_json::value::RawValue;
use serde_json::{Map, Value};

use crate::tina::util::json::JsonUtil;
use crate::tina::util::not_empty::INotEmpty;
use crate::{app_error_from, app_system_error, tina::data::AppResult};

/// 转换成JSON数据
pub trait ToJson {
    /// 转换成JSON Value
    fn to_json_value(&self) -> Value;
    /// 转换成JSON RawValue
    fn to_json_raw_value(&self) -> Box<RawValue>;
    /// 转换成JSON 字符串
    fn to_json_string(&self) -> String;
    /// 转换成JSON 格式化字符串
    fn to_json_string_pretty(&self) -> String;
}

/// 从JSON转换
pub trait FromJson {
    /// 从JSON 字符串 转换
    fn from_json_string(json_string: &str) -> AppResult<Self>
    where
        Self: Sized;
    /// 从JSON Value 转换
    fn from_json_value(json_value: &Value) -> AppResult<Self>
    where
        Self: Sized;
    /// 从JSON RawValue 转换
    fn from_json_raw_value(json_raw_value: &RawValue) -> AppResult<Self>
    where
        Self: Sized;
}

/// JSON数据转换
pub trait JsonToString {
    /// JSON转换成 字符串
    fn to_string_value(&self) -> String;
}

impl<S> ToJson for S
where
    S: Serialize,
{
    fn to_json_value(&self) -> Value {
        JsonUtil::to_json_value(&self)
    }

    fn to_json_raw_value(&self) -> Box<RawValue> {
        JsonUtil::to_json_raw_value(&self)
    }

    fn to_json_string(&self) -> String {
        JsonUtil::to_json_string(&self)
    }

    fn to_json_string_pretty(&self) -> String {
        JsonUtil::to_json_string_pretty(&self)
    }
}

impl<D> FromJson for D
where
    D: DeserializeOwned,
{
    fn from_json_string(json_string: &str) -> AppResult<Self>
    where
        Self: Sized,
    {
        JsonUtil::parse_json_string(json_string)
    }

    fn from_json_value(json_value: &Value) -> AppResult<Self>
    where
        Self: Sized,
    {
        JsonUtil::parse_json_value(json_value)
    }

    fn from_json_raw_value(json_raw_value: &RawValue) -> AppResult<Self>
    where
        Self: Sized,
    {
        JsonUtil::parse_json_raw_value(json_raw_value)
    }
}

impl<S> JsonToString for S
where
    S: Serialize,
{
    fn to_string_value(&self) -> String {
        match self.to_json_value() {
            Value::Null => "".to_string(),
            Value::Bool(v) => v.to_string(),
            Value::Number(v) => v.to_string(),
            Value::String(v) => v,
            Value::Array(v) => JsonUtil::to_json_string(&v),
            Value::Object(v) => JsonUtil::to_json_string(&v),
        }
    }
}

/// Json格式
pub trait JsonCaseExt<V> {
    /// 将 Key 转换成 snake case
    fn into_snake_case_key(self) -> V;
    /// 将 Key 转换成 lower camel case
    fn into_lower_camel_case_key(self) -> V;
    /// 将 Key 转换成 upper camel case
    fn into_upper_camel_case_key(self) -> V;
    /// 转成f64
    fn try_as_f64(&self) -> AppResult<f64>;
    /// 转成i64
    fn try_as_i64(&self) -> AppResult<i64>;
}

#[cfg(feature = "rbs")]
impl JsonCaseExt<rbs::Value> for rbs::Value {
    fn into_snake_case_key(self) -> rbs::Value {
        match self {
            rbs::Value::Array(v) => {
                if !v.not_empty() {
                    let mut list = Vec::with_capacity(v.len());
                    for item in v.into_iter() {
                        list.push(item.into_snake_case_key());
                    }
                    return rbs::Value::Array(list);
                }
                rbs::Value::Array(v)
            }
            rbs::Value::Map(v) => {
                if !v.is_empty() {
                    let mut map = rbs::value::map::ValueMap::new();
                    for (k, v) in v.into_iter() {
                        match k {
                            rbs::Value::String(k) => {
                                map.insert(rbs::Value::String(k.to_snake_case()), v.into_snake_case_key());
                            }
                            _ => {
                                map.insert(k, v.into_snake_case_key());
                            }
                        }
                    }
                    return rbs::Value::Map(map);
                }
                rbs::Value::Map(v)
            }
            _ => self,
        }
    }

    fn into_lower_camel_case_key(self) -> rbs::Value {
        match self {
            rbs::Value::Array(v) => {
                if !v.not_empty() {
                    let mut list = Vec::with_capacity(v.len());
                    for item in v.into_iter() {
                        list.push(item.into_lower_camel_case_key());
                    }
                    return rbs::Value::Array(list);
                }
                rbs::Value::Array(v)
            }
            rbs::Value::Map(v) => {
                if !v.is_empty() {
                    let mut map = rbs::value::map::ValueMap::new();
                    for (k, v) in v.into_iter() {
                        match k {
                            rbs::Value::String(k) => {
                                map.insert(rbs::Value::String(k.to_lower_camel_case()), v.into_lower_camel_case_key());
                            }
                            _ => {
                                map.insert(k, v.into_lower_camel_case_key());
                            }
                        }
                    }
                    return rbs::Value::Map(map);
                }
                rbs::Value::Map(v)
            }
            _ => self,
        }
    }

    fn into_upper_camel_case_key(self) -> rbs::Value {
        match self {
            rbs::Value::Array(v) => {
                if !v.not_empty() {
                    let mut list = Vec::with_capacity(v.len());
                    for item in v.into_iter() {
                        list.push(item.into_upper_camel_case_key());
                    }
                    return rbs::Value::Array(list);
                }
                rbs::Value::Array(v)
            }
            rbs::Value::Map(v) => {
                if !v.is_empty() {
                    let mut map = rbs::value::map::ValueMap::new();
                    for (k, v) in v.into_iter() {
                        match k {
                            rbs::Value::String(k) => {
                                map.insert(rbs::Value::String(k.to_upper_camel_case()), v.into_upper_camel_case_key());
                            }
                            _ => {
                                map.insert(k, v.into_upper_camel_case_key());
                            }
                        }
                    }
                    return rbs::Value::Map(map);
                }
                rbs::Value::Map(v)
            }
            _ => self,
        }
    }

    fn try_as_f64(&self) -> AppResult<f64> {
        match self {
            rbs::Value::I32(v) => Ok(*v as f64),
            rbs::Value::I64(v) => Ok(*v as f64),
            rbs::Value::U32(v) => Ok(*v as f64),
            rbs::Value::U64(v) => Ok(*v as f64),
            rbs::Value::F32(v) => Ok(*v as f64),
            rbs::Value::F64(v) => Ok(*v),
            rbs::Value::String(v) => v.parse::<f64>().map_err(app_error_from!()),
            _ => Err(app_system_error!("can not parse value to f64: {:?}", self)),
        }
    }

    fn try_as_i64(&self) -> AppResult<i64> {
        match self {
            rbs::Value::I32(v) => Ok(*v as i64),
            rbs::Value::I64(v) => Ok(*v),
            rbs::Value::U32(v) => Ok(*v as i64),
            rbs::Value::U64(v) => Ok(*v as i64),
            rbs::Value::F32(v) => Ok(*v as i64),
            rbs::Value::F64(v) => Ok(*v as i64),
            rbs::Value::String(v) => v.parse::<i64>().map_err(app_error_from!()),
            _ => Err(app_system_error!("can not parse value to i64: {:?}", self)),
        }
    }
}

impl JsonCaseExt<serde_json::Value> for serde_json::Value {
    fn into_snake_case_key(self) -> Value {
        match self {
            serde_json::Value::Array(v) => {
                if !v.not_empty() {
                    let mut list = Vec::with_capacity(v.len());
                    for item in v.into_iter() {
                        list.push(item.into_snake_case_key());
                    }
                    return serde_json::Value::Array(list);
                }
                serde_json::Value::Array(v)
            }
            serde_json::Value::Object(v) => {
                if !v.is_empty() {
                    let mut map = Map::new();
                    for (k, v) in v.into_iter() {
                        map.insert(k.to_snake_case(), v.into_snake_case_key());
                    }
                    return serde_json::Value::Object(map);
                }
                serde_json::Value::Object(v)
            }
            _ => self,
        }
    }

    fn into_lower_camel_case_key(self) -> Value {
        match self {
            serde_json::Value::Array(v) => {
                if !v.not_empty() {
                    let mut list = Vec::with_capacity(v.len());
                    for item in v.into_iter() {
                        list.push(item.into_lower_camel_case_key());
                    }
                    return serde_json::Value::Array(list);
                }
                serde_json::Value::Array(v)
            }
            serde_json::Value::Object(v) => {
                if !v.is_empty() {
                    let mut map = Map::new();
                    for (k, v) in v.into_iter() {
                        map.insert(k.to_lower_camel_case(), v.into_lower_camel_case_key());
                    }
                    return serde_json::Value::Object(map);
                }
                serde_json::Value::Object(v)
            }
            _ => self,
        }
    }

    fn into_upper_camel_case_key(self) -> Value {
        match self {
            serde_json::Value::Array(v) => {
                if !v.not_empty() {
                    let mut list = Vec::with_capacity(v.len());
                    for item in v.into_iter() {
                        list.push(item.into_upper_camel_case_key());
                    }
                    return serde_json::Value::Array(list);
                }
                serde_json::Value::Array(v)
            }
            serde_json::Value::Object(v) => {
                if !v.is_empty() {
                    let mut map = Map::new();
                    for (k, v) in v.into_iter() {
                        map.insert(k.to_upper_camel_case(), v.into_upper_camel_case_key());
                    }
                    return serde_json::Value::Object(map);
                }
                serde_json::Value::Object(v)
            }
            _ => self,
        }
    }

    fn try_as_f64(&self) -> AppResult<f64> {
        match self {
            Value::Number(v) => match v.as_f64() {
                Some(v) => Ok(v),
                None => match v.as_i64() {
                    Some(v) => Ok(v as f64),
                    None => match v.as_u64() {
                        Some(v) => Ok(v as f64),
                        None => Err(app_system_error!("can not parse value to f64: {:?}", v)),
                    },
                },
            },
            Value::String(s) => s.parse::<f64>().map_err(app_error_from!()),
            _ => Err(app_system_error!("can not parse value to f64: {:?}", self)),
        }
    }

    fn try_as_i64(&self) -> AppResult<i64> {
        match self {
            Value::Number(v) => match v.as_i64() {
                Some(v) => Ok(v),
                None => match v.as_u64() {
                    Some(v) => Ok(v as i64),
                    None => match v.as_f64() {
                        Some(v) => Ok(v as i64),
                        None => Err(app_system_error!("can not parse value to i64: {:?}", v)),
                    },
                },
            },
            Value::String(s) => s.parse::<i64>().map_err(app_error_from!()),
            _ => Err(app_system_error!("can not parse value to i64: {:?}", self)),
        }
    }
}