Skip to main content

neo_runtime/
json.rs

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