How to create a new Option<serde_json::Value> value?

Hi!

I resolved my previous problem but I'm stuck with another one:

I'm trying to create a new Postgres jsonb value and insert into the database:

let datadoc = Some(json!("a string"));
new_photo(&connection, datadoc);

And I'm getting this error:

15 | let datadoc = Some(json!("a string"));
| ^^^^^^^ expected enum std::option::Option, found struct database::schema::photo::datadoc
|
= note: expected type std::option::Option<serde_json::Value>
found type database::schema::photo::datadoc

and the function is here:

pub fn new_photo<'a>(conn: &PgConnection, datadoc: Option<serde_json::Value>) -> Photo {
use schema::photo;

let new_photo = NewPhoto {
    datadoc: datadoc,
};

diesel::insert_into(photo::table)
    .values(&new_photo)
    .get_result(conn)
    .expect("Error saving new post")

}

The model.rs is:

use super::schema::photo;
use serde_json;

#[derive(Queryable)]
pub struct Photo {
pub id: i64,
pub datadoc: Option<serde_json::Value>,
}

#[derive(Insertable)]
#[table_name="photo"]
pub struct NewPhoto {
pub datadoc: Option<serde_json::Value>,
}

and schema.rs is:

table! {
photo (id) {
id -> Int8,
datadoc -> Nullable,
}
}

I guess this is a very simple error, but I can't figure it out. Please help.

Can you share more of the code (maybe the whole crate on GitHub)? I don't think the problem is in the pieces you posted.

Yup, that's a good idea. I pushed the code to GitHub and the particular file which is causing the compile error is:

https://github.com/ikevin8me/photography/blob/master/src/main.rs

The method is at this file:

https://github.com/ikevin8me/photography/blob/master/database/src/lib.rs

The issue seems like diesel generates a struct called datadoc, and you have a local binding with the same name. Try changing your datadoc local to some other name.

When you invoke table!, we create a bunch of data structures to represent your schema. (See the guide Schema in Depth if you're interested in the specifics!). In particular, we create a struct to represent each column in your table. We also define a dsl module for convenience, which I'm assuming you glob imported based on your error message. That module looks like this:

pub mod dsl {
    pub use super::table as photo;
    pub use super::columns::*;
}

The second line is the important one. Inside the columns module, is a struct that looks like this:

pub struct datadoc;

This means there is a struct in scope with the name datadoc at the place where you're receiving an error message. One thing that might not be obvious if you're new to rust is that all let bindings are actually pattern matches. That's why you can write code like let (x, y) = some_tuple;. With that in mind, and knowing that datadoc is a struct with 0 fields, we can see that your code is being interpreted by rustc as:

let datadoc {} = Some(json!("a string"))

There are two solutions to this. The first is to simply change the name of your variable as others have mentioned. The other is to replace the line use schema::photos::dsl::*; with use schema::photos;, and reference photos as photos::table, and any columns as photos::column.

2 Likes

Works!

(I came from a Java background and didn't expect that. Anyway, thanks!!!)