Skip to main content

rust_eloquent/
types.rs

1use std::ops::{Deref, DerefMut};
2
3/// Transparent wrapper for JSON columns
4#[derive(Debug, Clone)]
5pub struct Json<T>(pub T);
6
7impl<T> Deref for Json<T> {
8    type Target = T;
9    fn deref(&self) -> &Self::Target {
10        &self.0
11    }
12}
13impl<T> DerefMut for Json<T> {
14    fn deref_mut(&mut self) -> &mut Self::Target {
15        &mut self.0
16    }
17}
18
19// Decode logic
20impl<'r, T: serde::de::DeserializeOwned> sqlx::Decode<'r, sqlx::Any> for Json<T> {
21    fn decode(value: sqlx::any::AnyValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
22        let text = <String as sqlx::Decode<sqlx::Any>>::decode(value)?;
23        let parsed = serde_json::from_str(&text)?;
24        Ok(Json(parsed))
25    }
26}
27
28// Encode logic
29impl<'q, T: serde::Serialize> sqlx::Encode<'q, sqlx::Any> for Json<T> {
30    fn encode_by_ref(&self, buf: &mut <sqlx::Any as sqlx::Database>::ArgumentBuffer<'q>) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + 'static + Send + Sync>> {
31        let text = serde_json::to_string(&self.0)?;
32        <String as sqlx::Encode<sqlx::Any>>::encode(text, buf)
33    }
34}
35
36// Type logic
37impl<T> sqlx::Type<sqlx::Any> for Json<T> {
38    fn type_info() -> sqlx::any::AnyTypeInfo {
39        <String as sqlx::Type<sqlx::Any>>::type_info()
40    }
41}
42
43impl<T: serde::Serialize> serde::Serialize for Json<T> {
44    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45    where
46        S: serde::Serializer,
47    {
48        self.0.serialize(serializer)
49    }
50}
51
52impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for Json<T> {
53    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
54    where
55        D: serde::Deserializer<'de>,
56    {
57        T::deserialize(deserializer).map(Json)
58    }
59}