-
-
Notifications
You must be signed in to change notification settings - Fork 504
Open
Description
One common case is to have a json column which should be deserialised to a struct.
Currently the postgres_type Json doesn't work if you also want Serialize and Deserialize.
use postgres_types::Json;
#[derive(Serialize, Deserialize, ToSql, FromSql, Debug)]
pub struct Product {
pub id: String,
pub data: Json<ProductData>,
}
#[derive(Serialize, Deserialize, ToSql, FromSql, Debug)]
pub struct ProductData {
pub a: String,
pub b: String,
}
It would be nice to add a derive which implements ToSql using Json.
The following could be the derive.
#[proc_macro_derive(ToSqlJson)]
pub fn postgres_mapper(input: TokenStream) -> TokenStream {
let mut ast: DeriveInput = syn::parse(input).expect("Couldn't parse item");
let name = &ast.ident;
let tokens = quote! {
use bytes::BytesMut;
use postgres_types::{accepts, to_sql_checked, IsNull, Json, Type};
impl ToSql for #name {
fn to_sql(
&self,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn std::error::Error + Sync + Send>> {
Json(self).to_sql(ty, out)
}
accepts!(JSON, JSONB);
to_sql_checked!();
}
};
tokens.into()
}
#[proc_macro_derive(FromSqlJson)]
pub fn postgres_mapper(input: TokenStream) -> TokenStream {
let mut ast: DeriveInput = syn::parse(input).expect("Couldn't parse item");
let name = &ast.ident;
let tokens = quote! {
use bytes::BytesMut;
use postgres_types::{accepts, Json, Type};
impl<'a> FromSql<'a> for #name {
fn from_sql(
ty: &Type,
raw: &[u8],
) -> Result<#name, Box<dyn std::error::Error + Sync + Send>> {
Json::<#name>::from_sql(ty, raw).map(|json| json.0)
}
accepts!(JSON, JSONB);
}
};
tokens.into()
}
As a Result the struct would now be:
#[derive(Serialize, Deserialize, ToSql, FromSql, Debug)]
pub struct Product {
pub id: String,
pub data: ProductData,
}
#[derive(Serialize, Deserialize, ToSqlJson, FromSqlJson, Debug)]
pub struct ProductData {
pub a: String,
pub b: String,
}
Metadata
Metadata
Assignees
Labels
No labels