use crate::error::{Error, Result};
use crate::parser::parse;
use crate::serializer::to_string;
use crate::value::Value;
use indexmap::IndexMap;
use serde_json;
pub fn json_to_toon(json_str: &str) -> Result<String> {
let json_value: serde_json::Value =
serde_json::from_str(json_str).map_err(|e| Error::Message(e.to_string()))?;
let toon_value = json_value_to_toon(&json_value);
to_string(&toon_value)
}
pub fn toon_to_json(toon_str: &str) -> Result<String> {
let toon_value = parse(toon_str)?;
let json_value = toon_value_to_json(&toon_value);
serde_json::to_string(&json_value).map_err(|e| Error::Message(e.to_string()))
}
pub fn toon_to_json_pretty(toon_str: &str) -> Result<String> {
let toon_value = parse(toon_str)?;
let json_value = toon_value_to_json(&toon_value);
serde_json::to_string_pretty(&json_value).map_err(|e| Error::Message(e.to_string()))
}
fn json_value_to_toon(json: &serde_json::Value) -> Value {
match json {
serde_json::Value::Null => Value::Null,
serde_json::Value::Bool(b) => Value::Bool(*b),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
Value::integer(i)
} else if let Some(f) = n.as_f64() {
Value::float(f)
} else {
Value::Number(n.to_string())
}
}
serde_json::Value::String(s) => Value::String(s.clone()),
serde_json::Value::Array(arr) => {
Value::Array(arr.iter().map(json_value_to_toon).collect())
}
serde_json::Value::Object(obj) => {
let mut map = IndexMap::new();
for (k, v) in obj {
map.insert(k.clone(), json_value_to_toon(v));
}
Value::Object(map)
}
}
}
fn toon_value_to_json(toon: &Value) -> serde_json::Value {
match toon {
Value::Null => serde_json::Value::Null,
Value::Bool(b) => serde_json::Value::Bool(*b),
Value::Number(n) => {
if let Ok(i) = n.parse::<i64>() {
serde_json::Value::Number(i.into())
} else if let Ok(f) = n.parse::<f64>() {
serde_json::Number::from_f64(f)
.map(serde_json::Value::Number)
.unwrap_or_else(|| serde_json::Value::String(n.clone()))
} else {
serde_json::Value::String(n.clone())
}
}
Value::String(s) => serde_json::Value::String(s.clone()),
Value::Array(arr) => {
serde_json::Value::Array(arr.iter().map(toon_value_to_json).collect())
}
Value::Object(obj) => {
let mut map = serde_json::Map::new();
for (k, v) in obj {
map.insert(k.clone(), toon_value_to_json(v));
}
serde_json::Value::Object(map)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_json_to_toon() {
let json = r#"{"id":123,"name":"Alice","active":true}"#;
let toon = json_to_toon(json).unwrap();
assert!(toon.contains("id: 123"));
assert!(toon.contains("name: Alice"));
assert!(toon.contains("active: true"));
}
#[test]
fn test_toon_to_json() {
let toon = r#"id: 123
name: Alice
active: true"#;
let json = toon_to_json(toon).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["id"], 123);
assert_eq!(parsed["name"], "Alice");
assert_eq!(parsed["active"], true);
}
#[test]
fn test_roundtrip() {
let original = r#"{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}"#;
let toon = json_to_toon(original).unwrap();
let json = toon_to_json(&toon).unwrap();
let orig_value: serde_json::Value = serde_json::from_str(original).unwrap();
let roundtrip_value: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(orig_value, roundtrip_value);
}
}