mruby_serde_json/json_value/
mod.rs1use std::cell::RefCell;
2use std::rc::Rc;
3
4use mrubyedge::Error;
5use mrubyedge::yamrb::helpers::mrb_funcall;
6use mrubyedge::yamrb::value::RObject;
7use mrubyedge::yamrb::value::RValue;
8use mrubyedge::yamrb::vm::VM;
9use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
10use serde_json::Value;
11
12pub struct Json<'a> {
13 mrb: Rc<RefCell<&'a mut VM>>,
14 inner: Rc<RObject>,
15}
16
17impl<'a> Json<'a> {
18 pub fn get_inner(&self) -> Rc<RObject> {
19 self.inner.clone()
20 }
21
22 pub fn from_robject(mrb: Rc<RefCell<&'a mut VM>>, inner: Rc<RObject>) -> Self {
23 Self { mrb, inner }
24 }
25}
26
27impl<'a> From<Json<'a>> for Rc<RObject> {
28 fn from(value: Json<'a>) -> Self {
29 value.get_inner()
30 }
31}
32
33impl<'a> Serialize for Json<'a> {
34 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35 where
36 S: Serializer,
37 {
38 match self.get_inner().value {
39 RValue::Nil => serializer.serialize_none(),
40 RValue::Bool(b) => serializer.serialize_bool(b),
41 RValue::Integer(i) => serializer.serialize_i64(i),
42 RValue::Float(f) => serializer.serialize_f64(f),
43 RValue::String(ref s, _) => {
44 serializer.serialize_str(&String::from_utf8_lossy(&s.borrow()))
45 }
46 RValue::Symbol(ref s) => serializer.serialize_str(&s.name),
47 RValue::Array(ref arr) => {
48 let arr = arr.borrow();
49 let mut seq = serializer.serialize_seq(Some(arr.len()))?;
50 for item in arr.iter() {
51 let json_item = Json::from_robject(self.mrb.clone(), item.clone());
52 seq.serialize_element(&json_item)?;
53 }
54 seq.end()
55 }
56 RValue::Hash(ref hash) => {
57 let hash = hash.borrow();
58 let mut map = serializer.serialize_map(Some(hash.len()))?;
59 for (_, (key, value)) in hash.iter() {
60 let key_str = match key.value {
61 RValue::String(ref s, _) => {
62 String::from_utf8_lossy(&s.borrow()).to_string()
63 }
64 RValue::Symbol(ref s) => s.name.to_string(),
65 _ => {
66 return Err(serde::ser::Error::custom("Non-string key in JSON object"));
67 }
68 };
69 let json_value = Json::from_robject(self.mrb.clone(), value.clone());
70 map.serialize_entry(&key_str, &json_value)?;
71 }
72 map.end()
73 }
74 _ => {
75 let obj = self.get_inner();
76 let vm = &mut self.mrb.borrow_mut();
77 let serializable = mrb_funcall(vm, Some(obj), "to_json", &[]);
78 let json_obj = Json::from_robject(
79 self.mrb.clone(),
80 serializable.expect("to_json not defined for instance"),
81 );
82 json_obj.serialize(serializer)
83 }
84 }
85 }
86}
87
88pub(crate) fn mrb_json_dump(vm: &mut VM, obj: Rc<RObject>) -> Result<Rc<RObject>, Error> {
89 let vm = Rc::new(RefCell::new(vm));
90 let json_value = Json::from_robject(vm, obj);
91 let serialized =
92 serde_json::to_string(&json_value).expect("Failed to serialize JSON value to string");
93 Ok(RObject::string(serialized).to_refcount_assigned())
94}
95
96pub struct JsonValue {
97 inner: Rc<RObject>,
98}
99
100impl JsonValue {
101 pub fn new(inner: Rc<RObject>) -> Self {
102 Self { inner }
103 }
104
105 pub fn get_inner(&self) -> Rc<RObject> {
106 self.inner.clone()
107 }
108}
109
110impl From<JsonValue> for Rc<RObject> {
111 fn from(value: JsonValue) -> Self {
112 value.get_inner()
113 }
114}
115
116impl From<Value> for JsonValue {
117 fn from(value: Value) -> Self {
118 let obj = match value {
119 Value::Null => RObject::nil().to_refcount_assigned(),
120 Value::Bool(b) => RObject::boolean(b).to_refcount_assigned(),
121 Value::Number(n) => {
122 if let Some(i) = n.as_i64() {
123 RObject::integer(i).to_refcount_assigned()
124 } else if let Some(u) = n.as_u64() {
125 RObject::integer(u as i64).to_refcount_assigned()
126 } else if let Some(f) = n.as_f64() {
127 RObject::float(f).to_refcount_assigned()
128 } else {
129 panic!("Invalid range of numeric value");
130 }
131 }
132 Value::String(s) => RObject::string(s).to_refcount_assigned(),
133 Value::Array(arr) => {
134 let vec = arr.into_iter().map(JsonValue::from).collect::<Vec<_>>();
135 let arr = RObject::array(vec.into_iter().map(|j| j.get_inner()).collect());
136 arr.to_refcount_assigned()
137 }
138 Value::Object(obj) => {
139 let map = obj
140 .into_iter()
141 .map(|(k, v)| {
142 let key = RObject::string(k).to_refcount_assigned();
143 (
144 key.as_hash_key().expect("object cannot use for hashed key"),
145 (key.clone(), JsonValue::from(v).get_inner()),
146 )
147 })
148 .collect();
149 let hash = RObject::hash(map);
150 hash.to_refcount_assigned()
151 }
152 };
153 JsonValue::new(obj)
154 }
155}
156
157pub(crate) fn mrb_json_load(_vm: &mut VM, json_str: impl Into<String>) -> Result<JsonValue, Error> {
158 let value = serde_json::from_str::<serde_json::Value>(&json_str.into())
159 .map_err(|e| Error::RuntimeError(format!("Failed to parse JSON string: {}", e)))?;
160 Ok(value.into())
161}