1use neo_types::*;
2use num_bigint::BigInt;
3use serde_json::{json, Value as JsonValue};
4use std::vec::Vec;
5
6pub 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}