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};
pub trait ToJson {
fn to_json_value(&self) -> Value;
fn to_json_raw_value(&self) -> Box<RawValue>;
fn to_json_string(&self) -> String;
fn to_json_string_pretty(&self) -> String;
}
pub trait FromJson {
fn from_json_string(json_string: &str) -> AppResult<Self>
where
Self: Sized;
fn from_json_value(json_value: &Value) -> AppResult<Self>
where
Self: Sized;
fn from_json_raw_value(json_raw_value: &RawValue) -> AppResult<Self>
where
Self: Sized;
}
pub trait JsonToString {
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),
}
}
}
pub trait JsonCaseExt<V> {
fn into_snake_case_key(self) -> V;
fn into_lower_camel_case_key(self) -> V;
fn into_upper_camel_case_key(self) -> V;
fn try_as_f64(&self) -> AppResult<f64>;
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)),
}
}
}