#diesel #derive #proc-macro #json #jsonb #expect #diesel-jsonb

diesel-json-derive

实现diesel-json-derive过程宏的宏crate

2个版本

0.1.1 2024年5月20日
0.1.0 2024年5月20日

#326过程宏

MIT 许可证

9KB

diesel-json-derive

注意: 这处于积极开发中。 不保证稳定性或可用性。 您可能希望使用 diesel_json。 请注意,此版本目前期望使用postgres。 欢迎提交支持其他后端的pull request。

diesel_json_derive

这是什么?这是一个过程宏,它自动为Diesel的 Jsonb 类型推导 ToSqlFromSql 特性。

考虑一个如下所示的表

CREATE TABLE foo (
  id TEXT PRIMARY KEY,
  bar JSONB NOT NULL
);

在Rust中可以表示为(无法编译!)

#[derive(Debug, Queryable, Identifiable, Insertable, AsChangeset, Selectable)]
#[diesel(table_name = crate::schema::foo)]
#[diesel(check_for_backend(diesel::pg::Pg))]
#[diesel(primary_key(id))]
struct Foo {
    id: String,
    bar: Bar,
}

struct Bar {
    x: i32,
}

为了使 Bar 被表示为jsonb blob,您需要实现 diesel::deserialize::FromSqldiesel::deserialize::FromSql 特性,例如如下所示

impl ToSql<Jsonb, Pg> for Foo {
    fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
        out.write_all(&[1])?;
        serde_json::to_writer(out, &self)?;
        Ok(serialize::IsNull::No)
    }
}

impl FromSql<Jsonb, Pg> for Foo {
    fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
        let bytes = bytes.as_bytes();
        if bytes[0] != 1 {
            return Err("Unsupported JSONB encoding version".into());
        }
        serde_json::from_slice(&bytes[1..]).map_err(|_| "Invalid Json".into())
    }
}

这很快变得单调乏味,因此这个crate为您完成了这项工作。因此,使用这个crate,您可以编写

use diesel::sql_types::Jsonb;
use diesel::{FromSqlRow, AsExpression};
use diesel_json_derive::DieselJsonb;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, AsExpression, FromSqlRow, DieselJsonb)]
#[diesel(sql_type = Jsonb)]
struct Bar {
    x: i32,
}

diesel_json_derive 与 ## diesel_json

diesel_json crate 解决了相同的问题,但它使用一个包装类型。这的缺点是,当进行匹配时,需要使用这种类型。这个crate没有这个缺点。

许可证:MIT

依赖

~300–750KB
~18K SLoC