cosmwasm_std/
serde.rs

1// This file simply re-exports some methods from serde_json
2// The reason is two fold:
3// 1. To easily ensure that all calling libraries use the same version (minimize code size)
4// 2. To allow us to switch out to eg. serde-json-core more easily
5
6use core::any::type_name;
7use serde::{de::DeserializeOwned, Serialize};
8
9use crate::Binary;
10use crate::{StdError, StdResult};
11
12#[deprecated = "use from_json instead"]
13pub fn from_slice<T: DeserializeOwned>(value: &[u8]) -> StdResult<T> {
14    from_json(value)
15}
16
17#[deprecated = "use from_json instead"]
18pub fn from_binary<T: DeserializeOwned>(value: &Binary) -> StdResult<T> {
19    from_json(value)
20}
21
22/// Deserializes the given JSON bytes to a data structure.
23///
24/// Errors if the input is not valid JSON or cannot be deserialized to the given type.
25pub fn from_json<T: DeserializeOwned>(value: impl AsRef<[u8]>) -> StdResult<T> {
26    serde_json_wasm::from_slice(value.as_ref())
27        .map_err(|e| StdError::parse_err(type_name::<T>(), e))
28}
29
30#[deprecated = "use to_json_vec instead"]
31pub fn to_vec<T>(data: &T) -> StdResult<Vec<u8>>
32where
33    T: Serialize + ?Sized,
34{
35    to_json_vec(data)
36}
37
38#[deprecated = "use to_json_binary instead"]
39pub fn to_binary<T>(data: &T) -> StdResult<Binary>
40where
41    T: Serialize + ?Sized,
42{
43    to_json_binary(data)
44}
45
46/// Serializes the given data structure as a JSON byte vector.
47pub fn to_json_vec<T>(data: &T) -> StdResult<Vec<u8>>
48where
49    T: Serialize + ?Sized,
50{
51    serde_json_wasm::to_vec(data).map_err(|e| StdError::serialize_err(type_name::<T>(), e))
52}
53
54/// Serializes the given data structure as a JSON string.
55pub fn to_json_string<T>(data: &T) -> StdResult<String>
56where
57    T: Serialize + ?Sized,
58{
59    serde_json_wasm::to_string(data).map_err(|e| StdError::serialize_err(type_name::<T>(), e))
60}
61
62/// Serializes the given data structure as JSON bytes.
63pub fn to_json_binary<T>(data: &T) -> StdResult<Binary>
64where
65    T: Serialize + ?Sized,
66{
67    to_json_vec(data).map(Binary::new)
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use serde::Deserialize;
74
75    #[derive(Serialize, Deserialize, Debug, PartialEq)]
76    #[serde(rename_all = "snake_case")]
77    enum SomeMsg {
78        Refund {},
79        ReleaseAll {
80            image: String,
81            amount: u32,
82            time: u64,
83            karma: i32,
84        },
85        Cowsay {
86            text: String,
87        },
88    }
89
90    #[test]
91    fn to_json_vec_works() {
92        let msg = SomeMsg::Refund {};
93        let serialized = to_json_vec(&msg).unwrap();
94        assert_eq!(serialized, br#"{"refund":{}}"#);
95
96        let msg = SomeMsg::ReleaseAll {
97            image: "foo".to_string(),
98            amount: 42,
99            time: 9007199254740999, // Number.MAX_SAFE_INTEGER + 7
100            karma: -17,
101        };
102        let serialized = String::from_utf8(to_json_vec(&msg).unwrap()).unwrap();
103        assert_eq!(
104            serialized,
105            r#"{"release_all":{"image":"foo","amount":42,"time":9007199254740999,"karma":-17}}"#
106        );
107    }
108
109    #[test]
110    fn from_json_works() {
111        let deserialized: SomeMsg = from_json(br#"{"refund":{}}"#).unwrap();
112        assert_eq!(deserialized, SomeMsg::Refund {});
113
114        let expected = SomeMsg::ReleaseAll {
115            image: "foo".to_string(),
116            amount: 42,
117            time: 18446744073709551615,
118            karma: -17,
119        };
120        // &[u8]
121        let deserialized: SomeMsg = from_json(
122            br#"{"release_all":{"image":"foo","amount":42,"time":18446744073709551615,"karma":-17}}"#,
123        )
124        .unwrap();
125        assert_eq!(deserialized, expected);
126
127        // &str
128        let deserialized: SomeMsg = from_json(
129            r#"{"release_all":{"image":"foo","amount":42,"time":18446744073709551615,"karma":-17}}"#,
130        )
131        .unwrap();
132        assert_eq!(deserialized, expected);
133    }
134
135    #[test]
136    fn from_json_or_binary() {
137        let msg = SomeMsg::Refund {};
138        let serialized: Binary = to_json_binary(&msg).unwrap();
139
140        let parse_binary: SomeMsg = from_json(&serialized).unwrap();
141        assert_eq!(parse_binary, msg);
142
143        let parse_slice: SomeMsg = from_json(serialized.as_slice()).unwrap();
144        assert_eq!(parse_slice, msg);
145    }
146
147    #[test]
148    fn to_json_vec_works_for_special_chars() {
149        let msg = SomeMsg::Cowsay {
150            text: "foo\"bar\\\"bla".to_string(),
151        };
152        let serialized = String::from_utf8(to_json_vec(&msg).unwrap()).unwrap();
153        assert_eq!(serialized, r#"{"cowsay":{"text":"foo\"bar\\\"bla"}}"#);
154    }
155
156    #[test]
157    fn from_json_works_for_special_chars() {
158        let deserialized: SomeMsg = from_json(br#"{"cowsay":{"text":"foo\"bar\\\"bla"}}"#).unwrap();
159        assert_eq!(
160            deserialized,
161            SomeMsg::Cowsay {
162                text: "foo\"bar\\\"bla".to_string(),
163            }
164        );
165    }
166
167    #[test]
168    fn to_json_string_works() {
169        let msg = SomeMsg::Refund {};
170        let serialized = to_json_string(&msg).unwrap();
171        assert_eq!(serialized, r#"{"refund":{}}"#);
172
173        let msg = SomeMsg::ReleaseAll {
174            image: "foo".to_string(),
175            amount: 42,
176            time: 9007199254740999, // Number.MAX_SAFE_INTEGER + 7
177            karma: -17,
178        };
179        let serialized = to_json_string(&msg).unwrap();
180        assert_eq!(
181            serialized,
182            r#"{"release_all":{"image":"foo","amount":42,"time":9007199254740999,"karma":-17}}"#
183        );
184    }
185}