fiddler_script/builtins/
json.rs1use indexmap::IndexMap;
4
5use crate::error::RuntimeError;
6use crate::Value;
7
8pub fn builtin_parse_json(args: Vec<Value>) -> Result<Value, RuntimeError> {
16 if args.len() != 1 {
17 return Err(RuntimeError::wrong_argument_count(1, args.len()));
18 }
19
20 let bytes = match &args[0] {
21 Value::Bytes(b) => b.clone(),
22 Value::String(s) => s.as_bytes().to_vec(),
23 _ => {
24 return Err(RuntimeError::invalid_argument(
25 "parse_json() requires bytes or string argument".to_string(),
26 ))
27 }
28 };
29
30 let json_value: serde_json::Value = serde_json::from_slice(&bytes)
31 .map_err(|e| RuntimeError::invalid_argument(format!("Invalid JSON: {}", e)))?;
32
33 Ok(json_to_value(json_value))
34}
35
36pub fn json_to_value(json: serde_json::Value) -> Value {
38 match json {
39 serde_json::Value::Null => Value::Null,
40 serde_json::Value::Bool(b) => Value::Boolean(b),
41 serde_json::Value::Number(n) => {
42 if let Some(i) = n.as_i64() {
43 Value::Integer(i)
44 } else if let Some(f) = n.as_f64() {
45 Value::Integer(f as i64)
47 } else {
48 Value::Null
49 }
50 }
51 serde_json::Value::String(s) => Value::String(s),
52 serde_json::Value::Array(arr) => Value::Array(arr.into_iter().map(json_to_value).collect()),
53 serde_json::Value::Object(obj) => {
54 let dict: IndexMap<String, Value> = obj
55 .into_iter()
56 .map(|(k, v)| (k, json_to_value(v)))
57 .collect();
58 Value::Dictionary(dict)
59 }
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn test_builtin_parse_json_string() {
69 let json = br#""hello""#.to_vec();
70 let result = builtin_parse_json(vec![Value::Bytes(json)]).unwrap();
71 assert_eq!(result, Value::String("hello".to_string()));
72 }
73
74 #[test]
75 fn test_builtin_parse_json_number() {
76 let json = b"42".to_vec();
77 let result = builtin_parse_json(vec![Value::Bytes(json)]).unwrap();
78 assert_eq!(result, Value::Integer(42));
79 }
80
81 #[test]
82 fn test_builtin_parse_json_boolean() {
83 let json = b"true".to_vec();
84 let result = builtin_parse_json(vec![Value::Bytes(json)]).unwrap();
85 assert_eq!(result, Value::Boolean(true));
86 }
87
88 #[test]
89 fn test_builtin_parse_json_null() {
90 let json = b"null".to_vec();
91 let result = builtin_parse_json(vec![Value::Bytes(json)]).unwrap();
92 assert_eq!(result, Value::Null);
93 }
94
95 #[test]
96 fn test_builtin_parse_json_from_string() {
97 let result =
98 builtin_parse_json(vec![Value::String(r#"{"key": "value"}"#.to_string())]).unwrap();
99 assert!(matches!(result, Value::Dictionary(_)));
100 if let Value::Dictionary(dict) = result {
101 assert_eq!(dict.get("key"), Some(&Value::String("value".to_string())));
102 }
103 }
104
105 #[test]
106 fn test_builtin_parse_json_invalid() {
107 let result = builtin_parse_json(vec![Value::Bytes(b"not valid json".to_vec())]);
108 assert!(matches!(result, Err(RuntimeError::InvalidArgument { .. })));
109 }
110}