Deserializing a jsonb (PostgreSQL data type) string using Diesel


#1

What seems quite straightforward from the docs, but I’m encountering into problems trying to deserialize a json string.

The data is obtained from the database using Diesel. The “datadoc”, which is what I’m trying to deserialize, is a PostgreSQL jsonb field type. The code loads it from the database and tries to deserialize it into “result”:

let results = photo
    .filter(sql(r#"datadoc @> '{"tags": ["food"]}'"#))
    .load::<Photo>(&connection)
    .expect("Error loading photos");
println!("Displaying {} photos", results.len());
for photo_data in results {
    let result : super::photo_actions::PhotoDataSave = super::serde_json::from_value(photo_data.datadoc).unwrap();
}

The error is:

error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
  --> src\contents.rs:31:60
   |
31 |         let result : super::photo_actions::PhotoDataSave = super::serde_json::from_value(photo_data.datadoc).unwrap();
   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: required because of the requirements on the impl of `for<'de> web::_IMPL_SERIALIZE_FOR_Photos::_serde::Deserialize<'de>` for `photo_actions::PhotoDataSave<'_>`
   = note: required because of the requirements on the impl of `web::_IMPL_SERIALIZE_FOR_Photos::_serde::de::DeserializeOwned` for `photo_actions::PhotoDataSave<'_>`
   = note: required by `serde_json::from_value`

The data structures are:

in schema.rs

table! {
    photo (id) {
        id -> Int8,
        datadoc -> Jsonb,
        created_timestamp -> Timestamp,
        modified_timestamp -> Timestamp,
    }
}

and in models.rs:

use super::schema::photo;
use serde_json;
use std::time::SystemTime;

#[derive(Queryable)]
pub struct Photo {
    pub id: i64,
    pub datadoc: serde_json::Value,
    pub created_timestamp: SystemTime,
    pub modified_timestamp: SystemTime,
}

#[derive(Insertable)]
#[table_name="photo"]
pub struct NewPhoto {
    pub datadoc: serde_json::Value,
    pub created_timestamp: SystemTime,
    pub modified_timestamp: SystemTime,
}

Help is appreciated. Thanks!


#2

I couldn’t resolve the 'de problem, but I by using a new data structure with Vec<String> I have resolved my issue:

#[derive(Serialize, Deserialize, Debug)]
pub struct PhotoDataLoad {
    pub filename: String,
    pub title_en: String,
    pub description_en: String,
    pub title_ja: String,
    pub description_ja: String,
    pub tags: Vec<String>,
}