Skip to main content

neo_runtime/
json.rs

1// Copyright (c) 2025-2026 R3E Network
2// Licensed under the MIT License
3
4use neo_types::*;
5use num_bigint::BigInt;
6use serde_json::{json, Value as JsonValue};
7use std::vec::Vec;
8
9/// Minimal JSON helpers to support tests.
10pub struct NeoJSON;
11
12impl NeoJSON {
13    pub fn serialize(value: &NeoValue) -> NeoResult<NeoString> {
14        let json_value = Self::value_to_json(value)?;
15        let text = serde_json::to_string(&json_value)
16            .map_err(|err| NeoError::new(&format!("failed to serialize JSON: {err}")))?;
17        Ok(NeoString::from_str(&text))
18    }
19
20    pub fn deserialize(json: &NeoString) -> NeoResult<NeoValue> {
21        let parsed: JsonValue = serde_json::from_str(json.as_str())
22            .map_err(|err| NeoError::new(&format!("failed to parse JSON: {err}")))?;
23        Self::json_to_value(&parsed)
24    }
25
26    fn value_to_json(value: &NeoValue) -> NeoResult<JsonValue> {
27        match value {
28            NeoValue::Integer(i) => Ok(json!({
29                "type": "Integer",
30                "value": i.as_bigint().to_string()
31            })),
32            NeoValue::Boolean(b) => Ok(json!({
33                "type": "Boolean",
34                "value": b.as_bool()
35            })),
36            NeoValue::String(s) => Ok(json!({
37                "type": "String",
38                "value": s.as_str()
39            })),
40            NeoValue::ByteString(bs) => {
41                let bytes: Vec<JsonValue> =
42                    bs.as_slice().iter().map(|b| JsonValue::from(*b)).collect();
43                Ok(json!({ "type": "ByteString", "value": bytes }))
44            }
45            NeoValue::Array(arr) => {
46                let mut values = Vec::new();
47                for item in arr.iter() {
48                    values.push(Self::value_to_json(item)?);
49                }
50                Ok(json!({ "type": "Array", "value": values }))
51            }
52            NeoValue::Map(map) => {
53                let mut entries = Vec::new();
54                for (key, value) in map.iter() {
55                    entries.push(json!({
56                        "key": Self::value_to_json(key)?,
57                        "value": Self::value_to_json(value)?,
58                    }));
59                }
60                Ok(json!({ "type": "Map", "value": entries }))
61            }
62            NeoValue::Struct(st) => {
63                let mut fields_json = Vec::new();
64                for (name, value) in st.iter() {
65                    fields_json.push(json!({
66                        "name": name,
67                        "value": Self::value_to_json(value)?,
68                    }));
69                }
70                Ok(json!({ "type": "Struct", "value": fields_json }))
71            }
72            NeoValue::Null => Ok(json!({ "type": "Null" })),
73        }
74    }
75
76    fn json_to_value(json: &JsonValue) -> NeoResult<NeoValue> {
77        let obj = json.as_object().ok_or(NeoError::InvalidType)?;
78        let kind = obj
79            .get("type")
80            .and_then(JsonValue::as_str)
81            .ok_or(NeoError::InvalidType)?;
82
83        match kind {
84            "Integer" => {
85                let value_str = obj
86                    .get("value")
87                    .and_then(JsonValue::as_str)
88                    .ok_or(NeoError::InvalidType)?;
89                let bigint =
90                    BigInt::parse_bytes(value_str.as_bytes(), 10).ok_or(NeoError::InvalidType)?;
91                Ok(NeoValue::from(NeoInteger::new(bigint)))
92            }
93            "Boolean" => {
94                let value = obj
95                    .get("value")
96                    .and_then(JsonValue::as_bool)
97                    .ok_or(NeoError::InvalidType)?;
98                Ok(NeoValue::from(NeoBoolean::new(value)))
99            }
100            "String" => {
101                let value = obj
102                    .get("value")
103                    .and_then(JsonValue::as_str)
104                    .ok_or(NeoError::InvalidType)?;
105                Ok(NeoValue::from(NeoString::from_str(value)))
106            }
107            "ByteString" => {
108                let array = obj
109                    .get("value")
110                    .and_then(JsonValue::as_array)
111                    .ok_or(NeoError::InvalidType)?;
112                let mut bytes = Vec::with_capacity(array.len());
113                for item in array {
114                    let byte = item.as_u64().ok_or(NeoError::InvalidType)?;
115                    let byte = u8::try_from(byte).map_err(|_| NeoError::InvalidType)?;
116                    bytes.push(byte);
117                }
118                Ok(NeoValue::from(NeoByteString::new(bytes)))
119            }
120            "Array" => {
121                let array = obj
122                    .get("value")
123                    .and_then(JsonValue::as_array)
124                    .ok_or(NeoError::InvalidType)?;
125                let mut values = NeoArray::new();
126                for item in array {
127                    values.push(Self::json_to_value(item)?);
128                }
129                Ok(NeoValue::from(values))
130            }
131            "Map" => {
132                let entries = obj
133                    .get("value")
134                    .and_then(JsonValue::as_array)
135                    .ok_or(NeoError::InvalidType)?;
136                let mut map = NeoMap::new();
137                for entry in entries {
138                    let entry_obj = entry.as_object().ok_or(NeoError::InvalidType)?;
139                    let key_json = entry_obj.get("key").ok_or(NeoError::InvalidType)?;
140                    let value_json = entry_obj.get("value").ok_or(NeoError::InvalidType)?;
141                    let key = Self::json_to_value(key_json)?;
142                    let value = Self::json_to_value(value_json)?;
143                    map.insert(key, value);
144                }
145                Ok(NeoValue::from(map))
146            }
147            "Struct" => {
148                let fields = obj
149                    .get("value")
150                    .and_then(JsonValue::as_array)
151                    .ok_or(NeoError::InvalidType)?;
152                let mut result = NeoStruct::new();
153                for field in fields {
154                    let field_obj = field.as_object().ok_or(NeoError::InvalidType)?;
155                    let name = field_obj
156                        .get("name")
157                        .and_then(JsonValue::as_str)
158                        .ok_or(NeoError::InvalidType)?;
159                    let value_json = field_obj.get("value").ok_or(NeoError::InvalidType)?;
160                    let value = Self::json_to_value(value_json)?;
161                    result = result.with_field(name, value);
162                }
163                Ok(NeoValue::from(result))
164            }
165            "Null" => Ok(NeoValue::Null),
166            _ => Err(NeoError::InvalidType),
167        }
168    }
169}