Merge pull request #373 from srijs/feat/json-newtype-wrapper

Add Json wrapper type
This commit is contained in:
Steven Fackler 2018-09-26 09:03:04 -07:00 committed by GitHub
commit b190738c23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 10 deletions

View File

@ -11,7 +11,7 @@ repository = "https://github.com/sfackler/rust-postgres"
"with-chrono-0.4" = ["chrono"] "with-chrono-0.4" = ["chrono"]
"with-eui48-0.3" = ["eui48"] "with-eui48-0.3" = ["eui48"]
"with-geo-0.10" = ["geo"] "with-geo-0.10" = ["geo"]
with-serde_json-1 = ["serde_json"] with-serde_json-1 = ["serde", "serde_json"]
"with-uuid-0.6" = ["uuid"] "with-uuid-0.6" = ["uuid"]
[dependencies] [dependencies]
@ -24,5 +24,6 @@ bit-vec = { version = "0.5", optional = true }
chrono = { version = "0.4", optional = true } chrono = { version = "0.4", optional = true }
eui48 = { version = "0.3", optional = true } eui48 = { version = "0.3", optional = true }
geo = { version = "0.10", optional = true } geo = { version = "0.10", optional = true }
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true } serde_json = { version = "1.0", optional = true }
uuid = { version = "0.6", optional = true } uuid = { version = "0.6", optional = true }

View File

@ -87,6 +87,9 @@ mod uuid;
mod special; mod special;
mod type_gen; mod type_gen;
#[cfg(feature = "with-serde_json-1")]
pub use self::serde_json::Json;
/// A Postgres type. /// A Postgres type.
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub struct Type(Inner); pub struct Type(Inner);

View File

@ -1,13 +1,22 @@
extern crate serde;
extern crate serde_json; extern crate serde_json;
use self::serde::{Deserialize, Serialize};
use self::serde_json::Value; use self::serde_json::Value;
use std::error::Error; use std::error::Error;
use std::io::{Read, Write}; use std::fmt::Debug;
use std::io::Read;
use types::{FromSql, IsNull, ToSql, Type}; use types::{FromSql, IsNull, ToSql, Type};
impl<'a> FromSql<'a> for Value { #[derive(Debug)]
fn from_sql(ty: &Type, mut raw: &[u8]) -> Result<Value, Box<Error + Sync + Send>> { pub struct Json<T>(pub T);
impl<'a, T> FromSql<'a> for Json<T>
where
T: Deserialize<'a>,
{
fn from_sql(ty: &Type, mut raw: &'a [u8]) -> Result<Json<T>, Box<Error + Sync + Send>> {
if *ty == Type::JSONB { if *ty == Type::JSONB {
let mut b = [0; 1]; let mut b = [0; 1];
raw.read_exact(&mut b)?; raw.read_exact(&mut b)?;
@ -16,7 +25,33 @@ impl<'a> FromSql<'a> for Value {
return Err("unsupported JSONB encoding version".into()); return Err("unsupported JSONB encoding version".into());
} }
} }
serde_json::de::from_reader(raw).map_err(Into::into) serde_json::de::from_slice(raw)
.map(Json)
.map_err(Into::into)
}
accepts!(JSON, JSONB);
}
impl<T> ToSql for Json<T>
where
T: Serialize + Debug,
{
fn to_sql(&self, ty: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
if *ty == Type::JSONB {
out.push(1);
}
serde_json::ser::to_writer(out, &self.0)?;
Ok(IsNull::No)
}
accepts!(JSON, JSONB);
to_sql_checked!();
}
impl<'a> FromSql<'a> for Value {
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Value, Box<Error + Sync + Send>> {
Json::<Value>::from_sql(ty, raw).map(|json| json.0)
} }
accepts!(JSON, JSONB); accepts!(JSON, JSONB);
@ -24,11 +59,7 @@ impl<'a> FromSql<'a> for Value {
impl ToSql for Value { impl ToSql for Value {
fn to_sql(&self, ty: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> { fn to_sql(&self, ty: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
if *ty == Type::JSONB { Json(self).to_sql(ty, out)
out.push(1);
}
write!(out, "{}", self)?;
Ok(IsNull::No)
} }
accepts!(JSON, JSONB); accepts!(JSON, JSONB);