use base64::{Engine as _, engine::general_purpose};
use serde_json::{Value, json};
use std::collections::HashMap;
fn serialize_value(value: &Value, visitor: &mut Visitor) -> Value {
if value.is_null() {
return json!({"v": "null"});
}
if let Some(b) = value.as_bool() {
return json!({"b": b});
}
if let Some(n) = value.as_f64() {
if n.is_infinite() {
if n.is_sign_positive() {
return json!({"v": "Infinity"});
} else {
return json!({"v": "-Infinity"});
}
}
if n.is_nan() {
return json!({"v": "NaN"});
}
if n == 0.0 && n.is_sign_negative() {
return json!({"v": "-0"});
}
return json!({"n": n});
}
if let Some(s) = value.as_str() {
return json!({"s": s});
}
if let Some(arr) = value.as_array() {
let value_ptr = value as *const Value as usize;
if let Some(ref_id) = visitor.visited.get(&value_ptr) {
return json!({"ref": ref_id});
}
let id = visitor.next_id();
visitor.visited.insert(value_ptr, id);
let serialized: Vec<Value> = arr
.iter()
.map(|item| serialize_value(item, visitor))
.collect();
return json!({"a": serialized, "id": id});
}
if let Some(obj) = value.as_object() {
let value_ptr = value as *const Value as usize;
if let Some(ref_id) = visitor.visited.get(&value_ptr) {
return json!({"ref": ref_id});
}
let id = visitor.next_id();
visitor.visited.insert(value_ptr, id);
let serialized: Vec<Value> = obj
.iter()
.map(|(key, val)| {
json!({
"k": key,
"v": serialize_value(val, visitor)
})
})
.collect();
return json!({"o": serialized, "id": id});
}
json!({"v": "undefined"})
}
struct Visitor {
visited: HashMap<usize, usize>,
id_counter: usize,
}
impl Visitor {
fn new() -> Self {
Self {
visited: HashMap::new(),
id_counter: 0,
}
}
fn next_id(&mut self) -> usize {
let id = self.id_counter;
self.id_counter += 1;
id
}
}
pub fn serialize_argument<T: serde::Serialize>(arg: &T) -> Value {
let json_value = serde_json::to_value(arg).unwrap_or(Value::Null);
let mut visitor = Visitor::new();
let value = serialize_value(&json_value, &mut visitor);
json!({
"value": value,
"handles": []
})
}
pub fn serialize_null() -> Value {
json!({
"value": {"v": "null"},
"handles": []
})
}
pub fn parse_value(value: &Value, refs: Option<&mut HashMap<usize, Value>>) -> Value {
let mut local_refs = HashMap::new();
let refs = match refs {
Some(r) => r,
None => &mut local_refs,
};
if value.is_null() {
return Value::Null;
}
if let Some(obj) = value.as_object() {
if let Some(ref_id) = obj.get("ref").and_then(|v| v.as_u64()) {
return refs.get(&(ref_id as usize)).cloned().unwrap_or(Value::Null);
}
if let Some(v) = obj.get("v").and_then(|v| v.as_str()) {
return match v {
"null" | "undefined" => Value::Null,
"Infinity" => {
serde_json::Number::from_f64(f64::INFINITY)
.map(Value::Number)
.unwrap_or(Value::Null)
}
"-Infinity" => serde_json::Number::from_f64(f64::NEG_INFINITY)
.map(Value::Number)
.unwrap_or(Value::Null),
"NaN" => serde_json::Number::from_f64(f64::NAN)
.map(Value::Number)
.unwrap_or(Value::Null),
"-0" => serde_json::Number::from_f64(-0.0)
.map(Value::Number)
.unwrap_or(json!(0.0)),
_ => Value::Null,
};
}
if let Some(b) = obj.get("b").and_then(|v| v.as_bool()) {
return json!(b);
}
if let Some(n) = obj.get("n") {
return n.clone();
}
if let Some(s) = obj.get("s").and_then(|v| v.as_str()) {
return json!(s);
}
if let Some(d) = obj.get("d").and_then(|v| v.as_str()) {
return json!(d);
}
if let Some(bi) = obj.get("bi").and_then(|v| v.as_str()) {
return json!(bi);
}
if let Some(u) = obj.get("u").and_then(|v| v.as_str()) {
return json!(u);
}
if let Some(error_obj) = obj.get("e").and_then(|v| v.as_object()) {
let mut result = serde_json::Map::new();
if let Some(message) = error_obj.get("m").and_then(|v| v.as_str()) {
result.insert("m".to_string(), json!(message));
}
if let Some(name) = error_obj.get("n").and_then(|v| v.as_str()) {
result.insert("n".to_string(), json!(name));
}
if let Some(stack) = error_obj.get("s").and_then(|v| v.as_str()) {
result.insert("s".to_string(), json!(stack));
}
return Value::Object(result);
}
if let Some(ta_obj) = obj.get("ta").and_then(|v| v.as_object()) {
let (Some(encoded), Some(kind)) = (
ta_obj.get("b").and_then(|v| v.as_str()),
ta_obj.get("k").and_then(|v| v.as_str()),
) else {
return Value::Null;
};
let Ok(decoded) = general_purpose::STANDARD.decode(encoded) else {
return Value::Null;
};
let mut result_array = Vec::new();
match kind {
"ui8" | "ui8c" => {
for byte in decoded {
result_array.push(json!(byte as u32));
}
}
"i8" => {
for byte in decoded {
result_array.push(json!(byte as i8 as i32));
}
}
"ui16" => {
for chunk in decoded.chunks(2) {
if chunk.len() == 2 {
let value = u16::from_le_bytes([chunk[0], chunk[1]]);
result_array.push(json!(value as u32));
}
}
}
"i16" => {
for chunk in decoded.chunks(2) {
if chunk.len() == 2 {
let value = i16::from_le_bytes([chunk[0], chunk[1]]);
result_array.push(json!(value as i32));
}
}
}
"i32" => {
for chunk in decoded.chunks(4) {
if chunk.len() == 4 {
let value =
i32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
result_array.push(json!(value as i64));
}
}
}
"ui32" => {
for chunk in decoded.chunks(4) {
if chunk.len() == 4 {
let value =
u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
result_array.push(json!(value as u64));
}
}
}
"f32" => {
for chunk in decoded.chunks(4) {
if chunk.len() == 4 {
let value =
f32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
result_array.push(json!(value));
}
}
}
"f64" => {
for chunk in decoded.chunks(8) {
if chunk.len() == 8 {
let value = f64::from_le_bytes([
chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5],
chunk[6], chunk[7],
]);
result_array.push(json!(value));
}
}
}
_ => {
for byte in decoded {
result_array.push(json!(byte));
}
}
}
return json!(result_array);
}
if let Some(arr) = obj.get("a").and_then(|v| v.as_array()) {
let result_arr: Vec<Value> = arr
.iter()
.map(|item| parse_value(item, Some(refs)))
.collect();
let result = json!(result_arr);
if let Some(id) = obj.get("id").and_then(|v| v.as_u64()) {
refs.insert(id as usize, result.clone());
}
return result;
}
if let Some(props) = obj.get("o").and_then(|v| v.as_array()) {
let mut result_obj = serde_json::Map::new();
for prop in props {
if let Some(prop_obj) = prop.as_object()
&& let (Some(key), Some(val)) = (
prop_obj.get("k").and_then(|v| v.as_str()),
prop_obj.get("v"),
)
{
result_obj.insert(key.to_string(), parse_value(val, Some(refs)));
}
}
let result = Value::Object(result_obj);
if let Some(id) = obj.get("id").and_then(|v| v.as_u64()) {
refs.insert(id as usize, result.clone());
}
return result;
}
}
Value::Null
}
pub fn parse_result(result: &Value) -> Value {
parse_value(result, None)
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
const PI: f64 = std::f64::consts::PI;
#[test]
fn test_serialize_null() {
let result = serialize_argument(&json!(null));
assert_eq!(
result,
json!({
"value": {"v": "null"},
"handles": []
})
);
}
#[test]
fn test_serialize_boolean() {
let result = serialize_argument(&json!(true));
assert_eq!(
result,
json!({
"value": {"b": true},
"handles": []
})
);
let result = serialize_argument(&json!(false));
assert_eq!(
result,
json!({
"value": {"b": false},
"handles": []
})
);
}
#[test]
fn test_serialize_number() {
let result = serialize_argument(&json!(42));
let value = &result["value"];
assert_eq!(value["n"].as_f64().unwrap(), 42.0);
assert_eq!(result["handles"], json!([]));
let result = serialize_argument(&json!(PI));
let value = &result["value"];
assert_eq!(value["n"].as_f64().unwrap(), PI);
assert_eq!(result["handles"], json!([]));
}
#[test]
fn test_serialize_special_floats() {
let result = serialize_argument(&json!(1.5));
let value = &result["value"];
assert_eq!(value["n"].as_f64().unwrap(), 1.5);
let result = serialize_argument(&json!(0.0));
let value = &result["value"];
assert_eq!(value["n"].as_f64().unwrap(), 0.0);
}
#[test]
fn test_serialize_string() {
let result = serialize_argument(&json!("hello"));
assert_eq!(
result,
json!({
"value": {"s": "hello"},
"handles": []
})
);
}
#[test]
fn test_serialize_array() {
let result = serialize_argument(&json!([1, 2, 3]));
assert_eq!(result["handles"], json!([]));
let value = &result["value"];
assert!(value["a"].is_array());
assert_eq!(value["id"], 0);
let items = value["a"].as_array().unwrap();
assert_eq!(items.len(), 3);
assert_eq!(items[0]["n"].as_f64().unwrap(), 1.0);
assert_eq!(items[1]["n"].as_f64().unwrap(), 2.0);
assert_eq!(items[2]["n"].as_f64().unwrap(), 3.0);
}
#[test]
fn test_serialize_object() {
let result = serialize_argument(&json!({
"name": "test",
"value": 42
}));
assert_eq!(result["handles"], json!([]));
let value = &result["value"];
assert!(value["o"].is_array());
assert_eq!(value["id"], 0);
let props = value["o"].as_array().unwrap();
assert_eq!(props.len(), 2);
let mut found_name = false;
let mut found_value = false;
for prop in props {
if prop["k"] == "name" {
assert_eq!(prop["v"], json!({"s": "test"}));
found_name = true;
}
if prop["k"] == "value" {
assert_eq!(prop["v"]["n"].as_f64().unwrap(), 42.0);
found_value = true;
}
}
assert!(found_name);
assert!(found_value);
}
#[test]
fn test_serialize_nested_array() {
let result = serialize_argument(&json!([1, "test", true, [2, 3]]));
let value = &result["value"];
let items = value["a"].as_array().unwrap();
assert_eq!(items.len(), 4);
assert_eq!(items[0]["n"].as_f64().unwrap(), 1.0);
assert_eq!(items[1], json!({"s": "test"}));
assert_eq!(items[2], json!({"b": true}));
assert_eq!(items[3]["id"], 1); let nested = items[3]["a"].as_array().unwrap();
assert_eq!(nested.len(), 2);
assert_eq!(nested[0]["n"].as_f64().unwrap(), 2.0);
assert_eq!(nested[1]["n"].as_f64().unwrap(), 3.0);
}
#[test]
fn test_serialize_nested_object() {
let result = serialize_argument(&json!({
"outer": {
"inner": "value"
}
}));
let value = &result["value"];
assert_eq!(value["id"], 0);
let props = value["o"].as_array().unwrap();
assert_eq!(props.len(), 1);
assert_eq!(props[0]["k"], "outer");
let inner_obj = &props[0]["v"];
assert_eq!(inner_obj["id"], 1);
let inner_props = inner_obj["o"].as_array().unwrap();
assert_eq!(inner_props.len(), 1);
assert_eq!(inner_props[0]["k"], "inner");
assert_eq!(inner_props[0]["v"], json!({"s": "value"}));
}
#[test]
fn test_serialize_mixed_types() {
let result = serialize_argument(&json!({
"string": "hello",
"number": 42,
"boolean": true,
"null": null,
"array": [1, 2, 3],
"object": {"nested": "value"}
}));
let value = &result["value"];
assert!(value["o"].is_array());
let props = value["o"].as_array().unwrap();
assert_eq!(props.len(), 6);
}
#[test]
fn test_serialize_null_helper() {
let result = serialize_null();
assert_eq!(
result,
json!({
"value": {"v": "null"},
"handles": []
})
);
}
#[test]
fn test_parse_null() {
let result = parse_value(&json!({"v": "null"}), None);
assert_eq!(result, Value::Null);
}
#[test]
fn test_parse_undefined() {
let result = parse_value(&json!({"v": "undefined"}), None);
assert_eq!(result, Value::Null);
}
#[test]
fn test_parse_boolean() {
let result = parse_value(&json!({"b": true}), None);
assert_eq!(result, json!(true));
let result = parse_value(&json!({"b": false}), None);
assert_eq!(result, json!(false));
}
#[test]
fn test_parse_number() {
let result = parse_value(&json!({"n": 42}), None);
assert_eq!(result.as_f64().unwrap(), 42.0);
let result = parse_value(&json!({"n": PI}), None);
assert_eq!(result.as_f64().unwrap(), PI);
}
#[test]
fn test_parse_special_floats() {
let result = parse_value(&json!({"v": "Infinity"}), None);
assert!(result.is_null());
let result = parse_value(&json!({"v": "-Infinity"}), None);
assert!(result.is_null());
let result = parse_value(&json!({"v": "NaN"}), None);
assert!(result.is_null());
let result = parse_value(&json!({"v": "-0"}), None);
assert!(result.is_number());
}
#[test]
fn test_parse_string() {
let result = parse_value(&json!({"s": "hello"}), None);
assert_eq!(result, json!("hello"));
let result = parse_value(&json!({"s": "world"}), None);
assert_eq!(result, json!("world"));
}
#[test]
fn test_parse_date() {
let result = parse_value(&json!({"d": "2025-12-25T00:00:00.000Z"}), None);
assert_eq!(result, json!("2025-12-25T00:00:00.000Z"));
let result = parse_value(&json!({"d": "2025-12-25T10:30:45.123Z"}), None);
assert_eq!(result, json!("2025-12-25T10:30:45.123Z"));
}
#[test]
fn test_parse_bigint() {
let result = parse_value(&json!({"bi": "12345678901234567890"}), None);
assert_eq!(result, json!("12345678901234567890"));
let result = parse_value(&json!({"bi": "9007199254740991"}), None);
assert_eq!(result, json!("9007199254740991"));
}
#[test]
fn test_parse_url() {
let result = parse_value(&json!({"u": "https://example.com"}), None);
assert_eq!(result, json!("https://example.com"));
let result = parse_value(&json!({"u": "https://example.com/path?query=1"}), None);
assert_eq!(result, json!("https://example.com/path?query=1"));
}
#[test]
fn test_parse_error() {
let result = parse_value(
&json!({
"e": {
"m": "Something went wrong",
"n": "TypeError",
"s": "Error: at line 1"
}
}),
None,
);
let obj = result.as_object().unwrap();
assert_eq!(
obj.get("m").and_then(|v| v.as_str()),
Some("Something went wrong")
);
assert_eq!(obj.get("n").and_then(|v| v.as_str()), Some("TypeError"));
assert_eq!(
obj.get("s").and_then(|v| v.as_str()),
Some("Error: at line 1")
);
}
#[test]
fn test_parse_typed_array_ui8() {
let values: Vec<u8> = vec![1, 2, 3, 4, 5];
let base64_encoded = general_purpose::STANDARD.encode(&values);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "ui8"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert_eq!(arr[i].as_u64().unwrap(), expected as u64);
}
}
#[test]
fn test_parse_typed_array_ui8c() {
let values: Vec<u8> = vec![1, 2, 3, 4, 5];
let base64_encoded = general_purpose::STANDARD.encode(&values);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "ui8c"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
assert_eq!(arr[0].as_u64().unwrap(), 1);
}
#[test]
fn test_parse_typed_array_i8() {
let values: Vec<i8> = vec![-1, 127, -128, 0, 1];
let bytes: Vec<u8> = values.iter().map(|&v| v as u8).collect();
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "i8"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert_eq!(arr[i].as_i64().unwrap(), expected as i64);
}
}
#[test]
fn test_parse_typed_array_ui16() {
let values: Vec<u16> = vec![1, 256, 65535];
let mut bytes = Vec::new();
for &v in &values {
bytes.extend_from_slice(&v.to_le_bytes());
}
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "ui16"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert_eq!(arr[i].as_u64().unwrap(), expected as u64);
}
}
#[test]
fn test_parse_typed_array_i16() {
let values: Vec<i16> = vec![1, -1, 32767, -32768];
let mut bytes = Vec::new();
for &v in &values {
bytes.extend_from_slice(&v.to_le_bytes());
}
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "i16"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert_eq!(arr[i].as_i64().unwrap(), expected as i64);
}
}
#[test]
fn test_parse_typed_array_ui32() {
let values: Vec<u32> = vec![1, 256, 4294967295];
let mut bytes = Vec::new();
for &v in &values {
bytes.extend_from_slice(&v.to_le_bytes());
}
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "ui32"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert_eq!(arr[i].as_u64().unwrap(), expected as u64);
}
}
#[test]
fn test_parse_typed_array_i32() {
let values: Vec<i32> = vec![1, -1, 2147483647, -2147483648];
let mut bytes = Vec::new();
for &v in &values {
bytes.extend_from_slice(&v.to_le_bytes());
}
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "i32"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert_eq!(arr[i].as_i64().unwrap(), expected as i64);
}
}
#[test]
fn test_parse_typed_array_f32() {
let values: Vec<f32> = vec![1.0, -1.0, PI as f32];
let mut bytes = Vec::new();
for &v in &values {
bytes.extend_from_slice(&v.to_le_bytes());
}
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "f32"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert!((arr[i].as_f64().unwrap() - expected as f64).abs() < 0.01);
}
}
#[test]
fn test_parse_typed_array_f64() {
let values: Vec<f64> = vec![1.0, -1.0, PI];
let mut bytes = Vec::new();
for &v in &values {
bytes.extend_from_slice(&v.to_le_bytes());
}
let base64_encoded = general_purpose::STANDARD.encode(&bytes);
let result = parse_value(&json!({"ta": {"b": base64_encoded, "k": "f64"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), values.len());
for (i, &expected) in values.iter().enumerate() {
assert!((arr[i].as_f64().unwrap() - expected).abs() < 0.0000001);
}
}
#[test]
fn test_parse_typed_array_empty() {
let result = parse_value(&json!({"ta": {"b": "", "k": "ui8"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), 0);
}
#[test]
fn test_parse_typed_array_invalid_base64() {
let result = parse_value(&json!({"ta": {"b": "not-valid-base64!", "k": "ui8"}}), None);
assert!(result.is_null());
}
#[test]
fn test_parse_typed_array_unknown_kind() {
let result = parse_value(&json!({"ta": {"b": "AQIDBAU=", "k": "unknown"}}), None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), 5);
assert_eq!(arr[0].as_u64().unwrap(), 1);
}
#[test]
fn test_parse_typed_array_missing_fields() {
let result = parse_value(&json!({"ta": {"k": "ui8"}}), None);
assert!(result.is_null());
let result = parse_value(&json!({"ta": {"b": "AQIDBAU="}}), None);
assert!(result.is_null());
}
#[test]
fn test_parse_circular_reference() {
let mut refs = HashMap::new();
refs.insert(5, json!([1, 2, 3]));
let result = parse_value(&json!({"ref": 5}), Some(&mut refs));
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), 3);
assert_eq!(arr[0].as_i64().unwrap(), 1);
}
#[test]
fn test_parse_array() {
let input = json!({
"a": [
{"n": 1},
{"n": 2},
{"n": 3}
],
"id": 0
});
let result = parse_value(&input, None);
assert!(result.is_array());
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), 3);
assert_eq!(arr[0].as_f64().unwrap(), 1.0);
assert_eq!(arr[1].as_f64().unwrap(), 2.0);
assert_eq!(arr[2].as_f64().unwrap(), 3.0);
}
#[test]
fn test_parse_object() {
let input = json!({
"o": [
{"k": "name", "v": {"s": "John"}},
{"k": "age", "v": {"n": 30}}
],
"id": 0
});
let result = parse_value(&input, None);
assert!(result.is_object());
let obj = result.as_object().unwrap();
assert_eq!(obj.get("name").and_then(|v| v.as_str()), Some("John"));
assert_eq!(obj.get("age").and_then(|v| v.as_f64()), Some(30.0));
}
#[test]
fn test_parse_nested_array() {
let input = json!({
"a": [
{"n": 1},
{"s": "test"},
{"b": true},
{
"a": [
{"n": 2},
{"n": 3}
],
"id": 1
}
],
"id": 0
});
let result = parse_value(&input, None);
let arr = result.as_array().unwrap();
assert_eq!(arr.len(), 4);
assert_eq!(arr[0].as_f64().unwrap(), 1.0);
assert_eq!(arr[1].as_str().unwrap(), "test");
assert!(arr[2].as_bool().unwrap());
let nested = arr[3].as_array().unwrap();
assert_eq!(nested.len(), 2);
assert_eq!(nested[0].as_f64().unwrap(), 2.0);
assert_eq!(nested[1].as_f64().unwrap(), 3.0);
}
#[test]
fn test_parse_nested_object() {
let input = json!({
"o": [
{
"k": "outer",
"v": {
"o": [
{"k": "inner", "v": {"s": "value"}}
],
"id": 1
}
}
],
"id": 0
});
let result = parse_value(&input, None);
let obj = result.as_object().unwrap();
let outer = obj.get("outer").unwrap().as_object().unwrap();
assert_eq!(outer.get("inner").and_then(|v| v.as_str()), Some("value"));
}
#[test]
fn test_parse_result() {
let result = parse_result(&json!({"s": "hello"}));
assert_eq!(result, json!("hello"));
let result = parse_result(&json!({"n": 42}));
assert_eq!(result.as_f64().unwrap(), 42.0);
}
#[test]
fn test_roundtrip_serialization() {
let original = json!({
"name": "test",
"value": 42,
"active": true,
"items": [1, 2, 3]
});
let serialized = serialize_argument(&original);
let serialized_value = &serialized["value"];
let deserialized = parse_value(serialized_value, None);
assert!(deserialized.is_object());
let obj = deserialized.as_object().unwrap();
assert_eq!(obj.get("name").and_then(|v| v.as_str()), Some("test"));
assert_eq!(obj.get("value").and_then(|v| v.as_f64()), Some(42.0));
assert_eq!(obj.get("active").and_then(|v| v.as_bool()), Some(true));
let items = obj.get("items").and_then(|v| v.as_array()).unwrap();
assert_eq!(items.len(), 3);
}
}