//! JSONBox 📋 - JSON解析・生成 // Nyashの箱システムによるJSON解析・生成を提供します。 // 参考: 既存Boxの設計思想 use crate::box_trait::{NyashBox, BoxCore, BoxBase, StringBox, BoolBox, IntegerBox}; use crate::boxes::array::ArrayBox; use crate::boxes::map_box::MapBox; use std::any::Any; use std::sync::RwLock; use serde_json::{Value, Error}; #[derive(Debug)] pub struct JSONBox { value: RwLock, base: BoxBase, } impl Clone for JSONBox { fn clone(&self) -> Self { let value_clone = self.value.read().unwrap().clone(); Self { value: RwLock::new(value_clone), base: BoxBase::new(), // New unique ID for clone } } } impl JSONBox { pub fn from_str(s: &str) -> Result { let value = serde_json::from_str(s)?; Ok(JSONBox { value: RwLock::new(value), base: BoxBase::new() }) } pub fn new(value: Value) -> Self { JSONBox { value: RwLock::new(value), base: BoxBase::new() } } pub fn to_string(&self) -> String { let value = self.value.read().unwrap(); value.to_string() } /// JSONパース pub fn parse(data: Box) -> Box { let json_str = data.to_string_box().value; match JSONBox::from_str(&json_str) { Ok(json_box) => Box::new(json_box), Err(e) => Box::new(StringBox::new(&format!("Error parsing JSON: {}", e))), } } /// JSON文字列化 pub fn stringify(&self) -> Box { Box::new(StringBox::new(&self.to_string())) } /// 値取得 pub fn get(&self, key: Box) -> Box { let key_str = key.to_string_box().value; let value = self.value.read().unwrap(); if let Some(obj) = value.as_object() { if let Some(val) = obj.get(&key_str) { json_value_to_nyash_box(val) } else { Box::new(crate::boxes::null_box::NullBox::new()) } } else if let Some(arr) = value.as_array() { if let Ok(index) = key_str.parse::() { if let Some(val) = arr.get(index) { json_value_to_nyash_box(val) } else { Box::new(crate::boxes::null_box::NullBox::new()) } } else { Box::new(crate::boxes::null_box::NullBox::new()) } } else { Box::new(crate::boxes::null_box::NullBox::new()) } } /// 値設定 pub fn set(&self, key: Box, new_value: Box) -> Box { let key_str = key.to_string_box().value; let mut value = self.value.write().unwrap(); let json_value = nyash_box_to_json_value(new_value); if let Some(obj) = value.as_object_mut() { obj.insert(key_str, json_value); Box::new(StringBox::new("ok")) } else { Box::new(StringBox::new("Error: JSONBox is not an object")) } } /// キー存在チェック pub fn has(&self, key: Box) -> Box { let key_str = key.to_string_box().value; let value = self.value.read().unwrap(); if let Some(obj) = value.as_object() { Box::new(BoolBox::new(obj.contains_key(&key_str))) } else { Box::new(BoolBox::new(false)) } } /// すべてのキーを取得 pub fn keys(&self) -> Box { let value = self.value.read().unwrap(); let array = ArrayBox::new(); if let Some(obj) = value.as_object() { for key in obj.keys() { // ArrayBoxのpushメソッドは&selfなので、直接呼び出し可能 let _ = array.push(Box::new(StringBox::new(key))); } } Box::new(array) } } impl BoxCore for JSONBox { fn box_id(&self) -> u64 { self.base.id } fn parent_type_id(&self) -> Option { self.base.parent_type_id } fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let value = self.value.read().unwrap(); let json_type = match *value { Value::Null => "null", Value::Bool(_) => "boolean", Value::Number(_) => "number", Value::String(_) => "string", Value::Array(ref arr) => { return write!(f, "JSONBox[array:{}]", arr.len()); }, Value::Object(ref obj) => { return write!(f, "JSONBox[object:{}]", obj.len()); }, }; write!(f, "JSONBox[{}]", json_type) } fn as_any(&self) -> &dyn Any { self } fn as_any_mut(&mut self) -> &mut dyn Any { self } } impl std::fmt::Display for JSONBox { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { self.fmt_box(f) } } impl NyashBox for JSONBox { fn clone_box(&self) -> Box { Box::new(self.clone()) } /// 仮実装: clone_boxと同じ(後で修正) fn share_box(&self) -> Box { self.clone_box() } fn to_string_box(&self) -> StringBox { let value = self.value.read().unwrap(); StringBox::new(value.to_string()) } fn type_name(&self) -> &'static str { "JSONBox" } fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(other_json) = other.as_any().downcast_ref::() { let self_value = self.value.read().unwrap(); let other_value = other_json.value.read().unwrap(); BoolBox::new(*self_value == *other_value) } else { BoolBox::new(false) } } } /// JSON Value を NyashBox に変換 fn json_value_to_nyash_box(value: &Value) -> Box { match value { Value::Null => Box::new(crate::boxes::null_box::NullBox::new()), Value::Bool(b) => Box::new(BoolBox::new(*b)), Value::Number(n) => { if let Some(i) = n.as_i64() { Box::new(IntegerBox::new(i)) } else if let Some(f) = n.as_f64() { // TODO: FloatBoxが実装されたら有効化 // Box::new(crate::boxes::float_box::FloatBox::new(f)) Box::new(StringBox::new(&f.to_string())) } else { Box::new(StringBox::new(&n.to_string())) } } Value::String(s) => Box::new(StringBox::new(s)), Value::Array(arr) => { let array_box = ArrayBox::new(); for item in arr { array_box.push(json_value_to_nyash_box(item)); } Box::new(array_box) } Value::Object(obj) => { let map_box = MapBox::new(); for (key, val) in obj { map_box.set( Box::new(StringBox::new(key)), json_value_to_nyash_box(val) ); } Box::new(map_box) } } } /// NyashBox を JSON Value に変換 fn nyash_box_to_json_value(value: Box) -> Value { if value.as_any().downcast_ref::().is_some() { Value::Null } else if let Some(bool_box) = value.as_any().downcast_ref::() { Value::Bool(bool_box.value) } else if let Some(int_box) = value.as_any().downcast_ref::() { Value::Number(serde_json::Number::from(int_box.value)) // TODO: FloatBoxが実装されたら有効化 // } else if let Some(float_box) = value.as_any().downcast_ref::() { // if let Some(n) = serde_json::Number::from_f64(float_box.value) { // Value::Number(n) // } else { // Value::String(float_box.value.to_string()) // } } else if let Some(string_box) = value.as_any().downcast_ref::() { Value::String(string_box.value.clone()) } else if let Some(array_box) = value.as_any().downcast_ref::() { let items = array_box.items.read().unwrap(); let arr: Vec = items.iter() .map(|item| nyash_box_to_json_value(item.clone_box())) .collect(); Value::Array(arr) } else if let Some(map_box) = value.as_any().downcast_ref::() { let data = map_box.get_data(); let map = data.read().unwrap(); let mut obj = serde_json::Map::new(); for (key, val) in map.iter() { obj.insert(key.clone(), nyash_box_to_json_value(val.clone_box())); } Value::Object(obj) } else { // その他の型は文字列に変換 Value::String(value.to_string_box().value) } }