JSON Documentation for SQLite? #5097
BackendSQLite Diesel version2.3.10 Diesel Featuresdiesel = { version = "2.3.10", features = ["sqlite", "chrono", "serde_json", "returning_clauses_for_sqlite_3_35"] } Operating System VersionmacOS Third party librariesNo response What do you want to do?I'm wondering if there is official documentation for integrating json with Diesel/Sqlite? Compile time errorN/A What code do you already have?This is what I'm currently doing.
#[derive(Queryable, Selectable, Debug)]
#[diesel(table_name = crate::schema::fingerprint_cache)]
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
pub struct FingerprintCache {
pub fingerprint_cache_id: i32,
pub last_used: NaiveDateTime,
response: String,
pub checksum: String,
}
impl FingerprintCache {
pub fn response(&self) -> Result<AcoustIdFingerprintResponse, serde_json::Error> {
serde_json::from_str(&self.response)
}
pub fn set_response(&mut self, response: AcoustIdFingerprintResponse) {
self.response = serde_json::to_string(&response).unwrap()
}
}Additional detailsI have found some random threads, but I'm wondering if there is some official json serialization/deserialization documentation for diesel with sqlite? Checklist
|
Replies: 5 comments 1 reply
|
There are two separate layers here: Diesel's SQL type and your app's domain type. For SQLite, Diesel does have JSON SQL marker types when the So your current approach is reasonable if the column is really just a cached JSON document. I would usually make that explicit: response: String,
pub fn response(&self) -> Result<AcoustIdFingerprintResponse, serde_json::Error> {
serde_json::from_str(&self.response)
}If you want SQLite to reject malformed values, add a migration-level check such as If you want Diesel to deserialize the column directly, use If this answers the SQLite JSON direction, please mark it as answered. |
Yeah, for simplicity I basically decided to do this setter/getter approach which works well enough for what I am doing, other than I wonder if should be storing with a binary format. Just to verify: Do you know if there is official documentation and examples for FromSql/ToSql? Or is this edge case enough that it isn't covered? |
|
Yes. The official references are the trait docs:
There are also source examples in Diesel itself. For SQLite JSON specifically, the built-in implementation is for
So a typed use diesel::deserialize::{self, FromSql};
use diesel::serialize::{self, IsNull, Output, ToSql};
use diesel::sql_types::Text;
use diesel::sqlite::{Sqlite, SqliteValue};
pub struct AcoustIdFingerprintResponseJson(pub AcoustIdFingerprintResponse);
impl FromSql<Text, Sqlite> for AcoustIdFingerprintResponseJson {
fn from_sql(value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
let raw = <String as FromSql<Text, Sqlite>>::from_sql(value)?;
serde_json::from_str(&raw)
.map(AcoustIdFingerprintResponseJson)
.map_err(Into::into)
}
}
impl ToSql<Text, Sqlite> for AcoustIdFingerprintResponseJson {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
out.set_value(serde_json::to_string(&self.0)?);
Ok(IsNull::No)
}
}Then your schema can stay For your cache case, I would still lean toward plain JSON text unless you specifically need SQLite JSONB. Text is easier to inspect, back up, and migrate, and Diesel's If that settles the direction, accepting the earlier answer would make the Q&A easier to find. |
|
Thank you! |
|
Just to leave this as comment here: I'm happy to review a PR that adds some documentation about adding custom type mappings for |
Yes. The official references are the trait docs:
FromSql: https://docs.rs/diesel/latest/diesel/deserialize/trait.FromSql.htmlToSql: https://docs.rs/diesel/latest/diesel/serialize/trait.ToSql.htmlThere are also source examples in Diesel itself. For SQLite JSON specifically, the built-in implementation is for
serde_json::Value, not a typed application struct:So a typed
AcoustIdFingerprintResponsecolumn is enough of an edge case that you will mostly compose the traits yourself rather than follow a dedicated cookbook page. The usual …