1extern crate serde_json;
4
5use std::io::prelude::*;
6
7use crate::deserialize::{self, FromSql};
8use crate::pg::{Pg, PgValue};
9use crate::serialize::{self, IsNull, Output, ToSql};
10use crate::sql_types;
11
12#[cfg(all(feature = "postgres_backend", feature = "serde_json"))]
13impl FromSql<sql_types::Json, Pg> for serde_json::Value {
14 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
15 serde_json::from_slice(value.as_bytes()).map_err(|_| "Invalid Json".into())
16 }
17}
18
19#[cfg(all(feature = "postgres_backend", feature = "serde_json"))]
20impl ToSql<sql_types::Json, Pg> for serde_json::Value {
21 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
22 serde_json::to_writer(out, self)
23 .map(|_| IsNull::No)
24 .map_err(Into::into)
25 }
26}
27
28#[cfg(all(feature = "postgres_backend", feature = "serde_json"))]
29impl FromSql<sql_types::Jsonb, Pg> for serde_json::Value {
30 fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
31 let bytes = value.as_bytes();
32 if bytes[0] != 1 {
33 return Err("Unsupported JSONB encoding version".into());
34 }
35 serde_json::from_slice(&bytes[1..]).map_err(|_| "Invalid Json".into())
36 }
37}
38
39#[cfg(all(feature = "postgres_backend", feature = "serde_json"))]
40impl ToSql<sql_types::Jsonb, Pg> for serde_json::Value {
41 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
42 out.write_all(&[1])?;
43 serde_json::to_writer(out, self)
44 .map(|_| IsNull::No)
45 .map_err(Into::into)
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use crate::deserialize::FromSql;
52 use crate::pg::{Pg, PgValue};
53 use crate::query_builder::bind_collector::ByteWrapper;
54 use crate::serialize::{Output, ToSql};
55 use crate::sql_types;
56
57 #[diesel_test_helper::test]
58 fn json_to_sql() {
59 let mut buffer = Vec::new();
60 let mut bytes = Output::test(ByteWrapper(&mut buffer));
61 let test_json = serde_json::Value::Bool(true);
62 ToSql::<sql_types::Json, Pg>::to_sql(&test_json, &mut bytes).unwrap();
63 assert_eq!(buffer, b"true");
64 }
65
66 #[diesel_test_helper::test]
67 fn some_json_from_sql() {
68 let input_json = b"true";
69 let output_json: serde_json::Value =
70 FromSql::<sql_types::Json, Pg>::from_sql(PgValue::for_test(input_json)).unwrap();
71 assert_eq!(output_json, serde_json::Value::Bool(true));
72 }
73
74 #[diesel_test_helper::test]
75 fn bad_json_from_sql() {
76 let uuid: Result<serde_json::Value, _> =
77 FromSql::<sql_types::Json, Pg>::from_sql(PgValue::for_test(b"boom"));
78 assert_eq!(uuid.unwrap_err().to_string(), "Invalid Json");
79 }
80
81 #[diesel_test_helper::test]
82 fn no_json_from_sql() {
83 let uuid: Result<serde_json::Value, _> =
84 FromSql::<sql_types::Json, Pg>::from_nullable_sql(None);
85 assert_eq!(
86 uuid.unwrap_err().to_string(),
87 "Unexpected null for non-null column"
88 );
89 }
90
91 #[diesel_test_helper::test]
92 fn jsonb_to_sql() {
93 let mut buffer = Vec::new();
94 let mut bytes = Output::test(ByteWrapper(&mut buffer));
95 let test_json = serde_json::Value::Bool(true);
96 ToSql::<sql_types::Jsonb, Pg>::to_sql(&test_json, &mut bytes).unwrap();
97 assert_eq!(buffer, b"\x01true");
98 }
99
100 #[diesel_test_helper::test]
101 fn some_jsonb_from_sql() {
102 let input_json = b"\x01true";
103 let output_json: serde_json::Value =
104 FromSql::<sql_types::Jsonb, Pg>::from_sql(PgValue::for_test(input_json)).unwrap();
105 assert_eq!(output_json, serde_json::Value::Bool(true));
106 }
107
108 #[diesel_test_helper::test]
109 fn bad_jsonb_from_sql() {
110 let uuid: Result<serde_json::Value, _> =
111 FromSql::<sql_types::Jsonb, Pg>::from_sql(PgValue::for_test(b"\x01boom"));
112 assert_eq!(uuid.unwrap_err().to_string(), "Invalid Json");
113 }
114
115 #[diesel_test_helper::test]
116 fn bad_jsonb_version_from_sql() {
117 let uuid: Result<serde_json::Value, _> =
118 FromSql::<sql_types::Jsonb, Pg>::from_sql(PgValue::for_test(b"\x02true"));
119 assert_eq!(
120 uuid.unwrap_err().to_string(),
121 "Unsupported JSONB encoding version"
122 );
123 }
124
125 #[diesel_test_helper::test]
126 fn no_jsonb_from_sql() {
127 let uuid: Result<serde_json::Value, _> =
128 FromSql::<sql_types::Jsonb, Pg>::from_nullable_sql(None);
129 assert_eq!(
130 uuid.unwrap_err().to_string(),
131 "Unexpected null for non-null column"
132 );
133 }
134}