Skip to main content

pamoja_codec/
json.rs

1//! A human-readable JSON codec built on [`serde_json`].
2
3use serde::de::DeserializeOwned;
4use serde::Serialize;
5
6use pamoja_core::{Error, Result};
7
8use crate::Codec;
9
10/// A codec that serializes values to and from JSON.
11///
12/// JSON trades the compactness of CBOR for human readability, which makes it a
13/// good fit for debugging, configuration, and interop with services that speak
14/// JSON. The codec works for any type that implements [`serde::Serialize`] and
15/// [`serde::de::DeserializeOwned`].
16///
17/// # Examples
18///
19/// ```
20/// use pamoja_codec::{Codec, JsonCodec};
21///
22/// let codec = JsonCodec;
23/// let encoded = codec.encode(&vec![1, 2, 3]).unwrap();
24/// assert_eq!(encoded, b"[1,2,3]");
25/// let decoded: Vec<i32> = codec.decode(&encoded).unwrap();
26/// assert_eq!(decoded, vec![1, 2, 3]);
27/// ```
28#[derive(Clone, Copy, Debug, Default)]
29pub struct JsonCodec;
30
31impl<T> Codec<T> for JsonCodec
32where
33    T: Serialize + DeserializeOwned,
34{
35    fn encode(&self, value: &T) -> Result<Vec<u8>> {
36        serde_json::to_vec(value).map_err(|error| Error::Codec(error.to_string()))
37    }
38
39    fn decode(&self, bytes: &[u8]) -> Result<T> {
40        serde_json::from_slice(bytes).map_err(|error| Error::Codec(error.to_string()))
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn round_trips_a_map() {
50        use std::collections::BTreeMap;
51
52        let codec = JsonCodec;
53        let mut value = BTreeMap::new();
54        value.insert("sensor".to_owned(), 21i64);
55        let encoded = codec.encode(&value).expect("encode");
56        let decoded: BTreeMap<String, i64> = codec.decode(&encoded).expect("decode");
57        assert_eq!(decoded, value);
58    }
59
60    #[test]
61    fn decoding_invalid_json_is_a_codec_error() {
62        let codec = JsonCodec;
63        let result: Result<Vec<i32>> = codec.decode(b"not json");
64        assert!(matches!(result, Err(Error::Codec(_))));
65    }
66}