Support serde's JSON type

This commit is contained in:
Steven Fackler 2015-04-12 21:48:38 -07:00
parent a3725a9522
commit 62459f6944
9 changed files with 76 additions and 8 deletions

View File

@ -5,8 +5,8 @@ before_script:
- "./.travis/setup.sh"
script:
- cargo test
- cargo test --features "uuid rustc-serialize time unix_socket"
- cargo doc --no-deps --features "uuid rustc-serialize time unix_socket"
- cargo test --features "uuid rustc-serialize time unix_socket serde"
- cargo doc --no-deps --features "uuid rustc-serialize time unix_socket serde"
after_success:
- test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && ./.travis/update_docs.sh
env:

View File

@ -33,6 +33,7 @@ debug-builders = "0.1"
uuid = { version = "0.1", optional = true }
unix_socket = { version = "0.3", optional = true }
time = { version = "0.1.14", optional = true }
serde = { version = "0.3", optional = true }
[dev-dependencies]
url = "0.2"

View File

@ -243,17 +243,22 @@ OSX, BSD and Linux.
### UUID type
[UUID](http://www.postgresql.org/docs/9.4/static/datatype-uuid.html) support is
provided optionally by the `uuid` feature.
provided optionally by the `uuid` feature, which adds `ToSql` and `FromSql`
implementations for `uuid`'s `Uuid` type.
### JSON/JSONB types
[JSON and JSONB](http://www.postgresql.org/docs/9.4/static/datatype-json.html)
support is provided optionally by the `rustc-serialize` feature.
support is provided optionally by the `rustc-serialize` feature, which adds
`ToSql` and `FromSql` implementations for `rustc-serialize`'s `Json` type and
the `serde` feature which adds implementations for `serde`'s `json::Value`
type.
### TIMESTAMP/TIMESTAMPTZ types
[TIMESTAMP and TIMESTAMPTZ](http://www.postgresql.org/docs/9.1/static/datatype-datetime.html)
support is provided optionally by the `time` feature.
support is provided optionally by the `time` feature, which adds `ToSql` and
`FromSql` implementations for `time`'s `Timespec` type.
## Development
Like Rust itself, Rust-Postgres is still in the early stages of development, so

View File

@ -48,7 +48,9 @@ mod uuid;
mod time;
mod slice;
#[cfg(feature = "rustc-serialize")]
mod json;
mod rustc_serialize;
#[cfg(feature = "serde")]
mod serde;
/// A Postgres OID
pub type Oid = u32;

37
src/types/serde.rs Normal file
View File

@ -0,0 +1,37 @@
extern crate serde;
use std::io::prelude::*;
use byteorder::{ReadBytesExt, WriteBytesExt};
use self::serde::json::{self, Value};
use {Result, Error};
use types::{FromSql, ToSql, IsNull, Type};
impl FromSql for Value {
fn from_sql<R: Read>(ty: &Type, raw: &mut R) -> Result<Value> {
if let Type::Jsonb = *ty {
// We only support version 1 of the jsonb binary format
if try!(raw.read_u8()) != 1 {
return Err(Error::BadResponse);
}
}
json::de::from_reader(raw).map_err(|_| Error::BadResponse)
}
accepts!(Type::Json, Type::Jsonb);
}
impl ToSql for Value {
fn to_sql<W: Write+?Sized>(&self, ty: &Type, mut out: &mut W) -> Result<IsNull> {
if let Type::Jsonb = *ty {
try!(out.write_u8(1));
}
try!(write!(out, "{:?}", self));
Ok(IsNull::No)
}
accepts!(Type::Json, Type::Jsonb);
to_sql_checked!();
}

View File

@ -11,7 +11,9 @@ mod uuid;
#[cfg(feature = "time")]
mod time;
#[cfg(feature = "rustc-serialize")]
mod json;
mod rustc_serialize;
#[cfg(feature = "serde")]
mod serde;
fn test_type<T: PartialEq+FromSql+ToSql, S: fmt::Display>(sql_type: &str, checks: &[(T, S)]) {
let conn = or_panic!(Connection::connect("postgres://postgres@localhost", &SslMode::None));

View File

@ -13,7 +13,6 @@ fn test_json_params() {
#[test]
fn test_jsonb_params() {
if option_env!("TRAVIS").is_some() { return } // Travis doesn't have Postgres 9.4 yet
test_type("JSONB", &[(Some(Json::from_str("[10, 11, 12]").unwrap()),
"'[10, 11, 12]'"),
(Some(Json::from_str("{\"f\": \"asd\"}").unwrap()),

22
tests/types/serde.rs Normal file
View File

@ -0,0 +1,22 @@
extern crate serde;
use self::serde::json::{self, Value};
use types::test_type;
#[test]
fn test_json_params() {
test_type("JSON", &[(Some(json::from_str::<Value>("[10, 11, 12]").unwrap()),
"'[10, 11, 12]'"),
(Some(json::from_str::<Value>("{\"f\": \"asd\"}").unwrap()),
"'{\"f\": \"asd\"}'"),
(None, "NULL")])
}
#[test]
fn test_jsonb_params() {
test_type("JSONB", &[(Some(json::from_str::<Value>("[10, 11, 12]").unwrap()),
"'[10, 11, 12]'"),
(Some(json::from_str::<Value>("{\"f\": \"asd\"}").unwrap()),
"'{\"f\": \"asd\"}'"),
(None, "NULL")])
}