1use core::fmt;
12
13use serde::{
14 Deserialize, Deserializer, Serialize, Serializer,
15 de::{self, Visitor},
16};
17
18use crate::Uuid;
19
20impl Serialize for Uuid {
21 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
22 serializer.collect_str(self)
23 }
24}
25
26struct UuidVisitor;
27
28impl<'de> Visitor<'de> for UuidVisitor {
29 type Value = Uuid;
30
31 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 f.write_str("a UUID as a 36-character hex string or 16-byte buffer")
33 }
34
35 fn visit_str<E: de::Error>(self, v: &str) -> Result<Uuid, E> {
36 Uuid::parse(v).map_err(de::Error::custom)
37 }
38
39 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Uuid, E> {
40 match v.len() {
43 16 => Uuid::from_slice(v).map_err(de::Error::custom),
44 36 => Uuid::parse(v).map_err(de::Error::custom),
45 _ => Err(de::Error::custom("expected 16 bytes (binary) or 36 bytes (hex string)")),
46 }
47 }
48}
49
50impl<'de> Deserialize<'de> for Uuid {
51 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Uuid, D::Error> {
52 deserializer.deserialize_bytes(UuidVisitor)
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use serde_json;
59
60 use super::*;
61
62 const S: &str = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
63
64 #[test]
65 fn round_trip() {
66 let uuid = Uuid::parse(S).unwrap();
67 let json = serde_json::to_string(&uuid).unwrap();
68 assert_eq!(json, format!("\"{S}\""));
69 let got: Uuid = serde_json::from_str(&json).unwrap();
70 assert_eq!(got, uuid);
71 }
72
73 #[test]
74 fn deserialize_from_str() {
75 let json = format!("\"{S}\"");
76 let uuid: Uuid = serde_json::from_str(&json).unwrap();
77 assert_eq!(uuid.to_string(), S);
78 }
79
80 #[test]
81 fn deserialize_array_rejected() {
82 let json = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]";
83 let result: Result<Uuid, _> = serde_json::from_str(json);
84 assert!(result.is_err());
85 }
86
87 #[test]
88 fn nil_round_trip() {
89 let uuid = Uuid::nil();
90 let json = serde_json::to_string(&uuid).unwrap();
91 assert_eq!(json, "\"00000000-0000-0000-0000-000000000000\"");
92 let got: Uuid = serde_json::from_str(&json).unwrap();
93 assert_eq!(got, uuid);
94 }
95}