Rust diesel with r2d2 load expected struct `Mysql`, found struct `Sqlite`? - mysql

I'm writing a database module for my rust application, use diesel.
Here's the compile error:
error[E0271]: type mismatch resolving `<MysqlConnection as Connection>::Backend == Sqlite`
--> src/quant/common/persistence/database.rs:155:18
|
155 | .load::<NetWorthModel>(&self.connection())
| ^^^^ expected struct `Mysql`, found struct `Sqlite`
|
= note: required because of the requirements on the impl of `LoadQuery<MysqlConnection, NetWorthModel>` for `diesel::query_builder::SelectStatement<table, diesel::query_builder::select_clause::DefaultSelectClause, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<And<And<diesel::expression::operators::Eq<columns::fund_code, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>>, GtEq<columns::date, diesel::expression::bound::Bound<diesel::sql_types::Date, std::string::String>>>, Lt<columns::date, diesel::expression::bound::Bound<diesel::sql_types::Date, std::string::String>>>>, diesel::query_builder::order_clause::OrderClause<Asc<columns::date>>, diesel::query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<diesel::sql_types::BigInt, i64>>, diesel::query_builder::offset_clause::OffsetClause<diesel::expression::bound::Bound<diesel::sql_types::BigInt, i64>>>`
Here's the model.rs:
use super::schema::tb_net_worth;
use diesel::{Identifiable, Insertable, Queryable};
#[derive(Queryable, Insertable, Identifiable)]
#[table_name = "tb_net_worth"]
#[primary_key(fund_code)]
pub struct NetWorthModel {
pub fund_code: String,
pub date: String,
pub create_time: i64,
pub update_time: i64,
pub payload: String,
}
Here's my source code database.rs:
use crate::quant::common::persistence::model::NetWorthModel;
use crate::quant::common::yadatetime::Date;
use diesel::mysql::MysqlConnection;
use diesel::prelude::*;
use diesel::r2d2::{ConnectionManager, Pool};
use std::collections::HashMap;
use std::sync::Mutex;
pub struct MysqlDatabase {
pool: Pool<ConnectionManager<MysqlConnection>>,
}
impl MysqlDatabase {
fn new(user: &str, passwd: &str, host: &str, port: i32, db: &str) -> MysqlDatabase {
let url = format!("mysql://{}:{}#{}:{}/{}", user, passwd, host, port, db);
let pool_manager = ConnectionManager::<MysqlConnection>::new(url.as_str());
let pool = Pool::builder()
.max_size(16)
.build(pool_manager)
.unwrap();
MysqlDatabase {pool: pool.clone()}
}
fn connection(&self) -> MysqlConnection {
*self.pool.get().unwrap()
}
fn paged_query(&self,
fund_code: &str,
order_by: &str,
start_date: Date,
end_date: Date,
page_index: i32,
page_size: i32) -> Vec[NetWorthModel] {
use super::schema::tb_net_worth::dsl;
let query = dsl::tb_net_worth
.filter(dsl::fund_code.eq(fund_code))
.filter(dsl::date.ge(start_date.to_string()))
.filter(dsl::date.lt(end_date.to_string()));
if order_by == "ASC" {
query.order(dsl::date.asc())
.limit(page_size as i64)
.offset((page_index * page_size) as i64)
.load<NetWorthModel>(&self.connection())
.unwrap()
} else {
query.order(dsl::date.desc())
.limit(page_size as i64)
.offset((page_index * page_size) as i64)
.load<NetWorthModel>(&self.connection())
.unwrap()
}
}
Would you please help with that ?

Related

Serialize/Deserialize CSV with nested enum/struct with serde in Rust

I want to serialize/deserialize a CSV file with variable row length and content, like the following:
./test.csv
Message,20200202T102030,Some message content
Measurement,20200202T102031,10,30,40,2
AnotherMeasurement,20200202T102034,0,2
In my opinion, the easiest way to represent this is the following enum:
#[derive(Debug, Serialize, Deserialize)]
pub enum Record {
Message { timestamp: String, content: String }, // timestamp is String because of simplicity
Measurement { timestamp: String, a: u32, b: u32, c: u32, d: u32 },
AnotherMeasurement { timestamp: String, a: u32, b: u32 },
}
Cargo.toml
[dependencies]¬
csv = "^1.1.6"¬
serde = { version = "^1", features = ["derive"] }
Running the following
main.rs
fn example() -> Result<(), Box<dyn Error>> {
let mut rdr = csv::ReaderBuilder::new()
.has_headers(false)
.delimiter(b',')
.flexible(true)
.double_quote(false)
.from_path("./test.csv")
.unwrap();
for result in rdr.deserialize() {
let record: Record = result?;
println!("{:?}", record);
}
Ok(())
}
fn write_msg() -> Result<(), Box<dyn Error>> {
let msg = Record::Message {
timestamp: String::from("time"),
content: String::from("content"),
};
let mut wtr = csv::WriterBuilder::new()
.has_headers(false)
.flexible(true)
.double_quote(false)
.from_writer(std::io::stdout());
wtr.serialize(msg)?;
wtr.flush()?;
Ok(())
}
fn main() {
if let Err(err) = example() {
println!("error running example: {}", err);
}
if let Err(err) = write_msg() {
println!("error running example: {}", err);
}
}
prints
error running example: CSV deserialize error: record 0 (line: 1, byte: 0): invalid type: unit variant, expected struct variant
error running example: CSV write error: serializing enum struct variants is not supported
Is there an easy solution to do this with serde and csv? I feel like I missed one or two serde attributes, but I was not able to find the right one in the documentation yet.
EDITS
Netwave suggested adding the #[serde(tag = "type")] attribute. Serializing now works, Deserializing gives the following error:
error running example: CSV deserialize error: record 0 (line: 1, byte: 0): invalid type: string "Message", expected internally tagged enum Record
Research I did that did not lead to a solution yet
Is there a way to "flatten" enums for (de)serialization in Rust?
https://docs.rs/csv/1.1.6/csv/tutorial/index.html
Custom serde serialization for enum type
https://serde.rs/enum-representations.html
Make your enum tagged (internally tagged specifically):
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Record {
Message { timestamp: String, content: String }, // timestamp is String because of simplicity
Measurement { timestamp: String, a: u32, b: u32, c: u32, d: u32 },
AnotherMeasurement { timestamp: String, a: u32, b: u32 },
}
Playground

how can I fix sql type error with diesel and juniper for mysql in graphQL mutation?

I confronted the error logs below when I try to create mutation with graphGL and mysql via diesel.
currently the type of enum is just diesel's type but I want to make that with graphQl's type.
I implemented Customer Structure for graphQL like below.
is it not enough ? and do you have any idea to fix that ?
Thanks
Error log
error[E0277]: the trait bound `graphql::Customer: diesel::Queryable<(diesel::sql_types::Unsigned<diesel::sql_types::BigInt>, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), _>` is not satisfied
--> src/graphql.rs:60:14
|
60 | .first::<crate::graphql::Customer>(&executor.context().db_con)
| ^^^^^ the trait `diesel::Queryable<(diesel::sql_types::Unsigned<diesel::sql_types::BigInt>, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), _>` is not implemented for `graphql::Customer`
|
= note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, graphql::Customer>` for `diesel::query_builder::SelectStatement<schema::customers::table, diesel::query_builder::select_clause::DefaultSelectClause, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::NoWhereClause, diesel::query_builder::order_clause::NoOrderClause, diesel::query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<diesel::sql_types::BigInt, i64>>>`
src/graphql.rs
use std::convert::From;
use std::sync::Arc;
use chrono::NaiveDateTime;
use actix_web::{web, Error, HttpResponse};
use futures01::future::Future;
use juniper::http::playground::playground_source;
use juniper::{http::GraphQLRequest, Executor, FieldResult, FieldError,ID};
use juniper_from_schema::graphql_schema_from_file;
use diesel::prelude::*;
use itertools::Itertools;
use crate::schema::customers;
use crate::{DbCon, DbPool};
graphql_schema_from_file!("src/schema.graphql");
pub struct Context {
db_con: DbCon,
}
impl juniper::Context for Context {}
pub struct Query;
pub struct Mutation;
impl QueryFields for Query {
fn field_customers(
&self,
executor: &Executor<'_, Context>,
_trail: &QueryTrail<'_, Customer, Walked>,
) -> FieldResult<Vec<Customer>> {
//type FieldResult<T> = Result<T, String>;
customers::table
.load::<crate::models::Customer>(&executor.context().db_con)
.and_then(|customers| Ok(customers.into_iter().map_into().collect()))
.map_err(Into::into)
}
}
impl MutationFields for Mutation {
fn field_create_customer(
&self,
executor: &Executor<'_, Context>,
_trail: &QueryTrail<'_, Customer, Walked>,
name: String,
email: String,
) -> FieldResult<Customer> {
//type FieldResult<T> = Result<T, String>;
let new_customer = crate::models::NewCustomer { name: name, email: email};
diesel::insert_into(customers::table)
.values(&new_customer)
.execute(&executor.context().db_con);
customers::table
.first::<crate::graphql::Customer>(&executor.context().db_con)
.map_err(Into::into)
}
}
pub struct Customer {
id: u64,
name: String,
email: String,
created_at: NaiveDateTime,
updated_at: NaiveDateTime,
}
impl CustomerFields for Customer {
fn field_id(&self, _: &Executor<'_, Context>) -> FieldResult<juniper::ID> {
Ok(juniper::ID::new(self.id.to_string()))
}
fn field_name(&self, _: &Executor<'_, Context>) -> FieldResult<&String> {
Ok(&self.name)
}
fn field_email(&self, _: &Executor<'_, Context>) -> FieldResult<&String> {
Ok(&self.email)
}
}
impl From<crate::models::Customer> for Customer {
fn from(customer: crate::models::Customer) -> Self {
Self {
id: customer.id,
name: customer.name,
email: customer.email,
created_at: customer.created_at,
updated_at: customer.updated_at,
}
}
}
fn playground() -> HttpResponse {
let html = playground_source("");
HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(html)
}
fn graphql(
schema: web::Data<Arc<Schema>>,
data: web::Json<GraphQLRequest>,
db_pool: web::Data<DbPool>,
) -> impl Future<Item = HttpResponse, Error = Error> {
let ctx = Context {
db_con: db_pool.get().unwrap(),
};
web::block(move || {
let res = data.execute(&schema, &ctx);
Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?)
})
.map_err(Error::from)
.and_then(|customer| {
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(customer))
})
}
pub fn register(config: &mut web::ServiceConfig) {
let schema = std::sync::Arc::new(Schema::new(Query, Mutation));
config
.data(schema)
.route("/", web::post().to_async(graphql))
.route("/", web::get().to(playground));
}
src/models.rs
#[derive(Queryable, Identifiable, AsChangeset, Clone, PartialEq, Debug)]
pub struct Customer {
pub id: u64,
pub name: String,
pub email: String,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
}
use super::schema::customers;
#[derive(Queryable,Insertable, AsChangeset)]
#[table_name="customers"]
pub struct NewCustomer {
pub name: String,
pub email: String,
}
Dependencies
[dependencies]
diesel = { version = "1.4.5", features = ["mysql", "r2d2", "chrono"] }
dotenv = "~0.15"
serde = "~1.0"
serde_derive = "~1.0"
serde_json = "~1.0"
chrono = "~0.4"
rand = "0.7.3"
actix-web = "1.0.9"
actix-cors = "0.1.0"
juniper = "0.14.1"
juniper-from-schema = "0.5.1"
juniper-eager-loading = "0.5.0"
r2d2_mysql = "*"
r2d2-diesel = "0.16.0"
mysql = "*"
r2d2 = "*"
futures01 = "0.1.29"
itertools = "0.8.2"
src/schema.graphql
schema {
query: Query
mutation: Mutation
}
type Query {
customers: [Customer!]! #juniper(ownership: "owned")
}
type Mutation {
createCustomer(
name: String!,
email: String!,
): Customer! #juniper(ownership: "owned")
}
type Customer {
id: ID! #juniper(ownership: "owned")
name: String!
email: String!
}
src/schema.rs
table! {
customers (id) {
id -> Unsigned<Bigint>,
name -> Varchar,
email -> Varchar,
created_at -> Timestamp,
updated_at -> Timestamp,
}
}
As the error message mentions you need to implement Queryable for your struct Customer in src/graphql.rs (That struct in just below where the error message points to). The easiest way to do that is to just add a #[derive(Queryable)] to this struct.

How do I deserialize a struct that has a generic type that implements a trait? [duplicate]

I want to use Serde to create an array with error messages as well as proper objects:
extern crate serde; // 1.0.70
#[macro_use]
extern crate serde_derive; // 1.0.70
extern crate serde_json; // 1.0.24
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
fn get_results(ages: Vec<i32>) -> Vec<MyAge> {
let mut results = vec![];
for age in ages {
if age < 100 && age > 0 {
results.push(MyAge {
age: age,
name: String::from("The dude"),
});
} else {
results.push(MyError {
error: String::from(format!("{} is invalid age", age)),
});
}
}
results
}
When I pass in the Vec [1, -6, 7] I want to serialize to the JSON:
[{"age": 1, "name": "The dude"},{"error": "-6 is invalid age"},{"age": 7, "name": "The dude"}]
How do I do that? Knowing how to deserialize such an array would be nice as well.
Here's one way of doing that:
#[macro_use]
extern crate serde_derive; // 1.0.117
extern crate serde; // 1.0.117
extern crate serde_json; // 1.0.59
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Debug)]
enum AgeOrError {
Age(MyAge),
Error(MyError),
}
impl serde::Serialize for AgeOrError {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
&AgeOrError::Age(ref my_age) => serializer.serialize_some(my_age),
&AgeOrError::Error(ref my_error) => serializer.serialize_some(my_error),
}
}
}
enum AgeOrErrorField {
Age,
Name,
Error,
}
impl<'de> serde::Deserialize<'de> for AgeOrErrorField {
fn deserialize<D>(deserializer: D) -> Result<AgeOrErrorField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct AgeOrErrorFieldVisitor;
impl<'de> serde::de::Visitor<'de> for AgeOrErrorFieldVisitor {
type Value = AgeOrErrorField;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "age or error")
}
fn visit_str<E>(self, value: &str) -> Result<AgeOrErrorField, E>
where
E: serde::de::Error,
{
Ok(match value {
"age" => AgeOrErrorField::Age,
"name" => AgeOrErrorField::Name,
"error" => AgeOrErrorField::Error,
_ => panic!("Unexpected field name: {}", value),
})
}
}
deserializer.deserialize_any(AgeOrErrorFieldVisitor)
}
}
impl<'de> serde::Deserialize<'de> for AgeOrError {
fn deserialize<D>(deserializer: D) -> Result<AgeOrError, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(AgeOrErrorVisitor)
}
}
struct AgeOrErrorVisitor;
impl<'de> serde::de::Visitor<'de> for AgeOrErrorVisitor {
type Value = AgeOrError;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "age or error")
}
fn visit_map<A>(self, mut map: A) -> Result<AgeOrError, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut age: Option<i32> = None;
let mut name: Option<String> = None;
let mut error: Option<String> = None;
loop {
match map.next_key()? {
Some(AgeOrErrorField::Age) => age = map.next_value()?,
Some(AgeOrErrorField::Name) => name = map.next_value()?,
Some(AgeOrErrorField::Error) => error = map.next_value()?,
None => break,
}
}
if let Some(error) = error {
Ok(AgeOrError::Error(MyError { error: error }))
} else {
Ok(AgeOrError::Age(MyAge {
age: age.expect("!age"),
name: name.expect("!name"),
}))
}
}
}
fn get_results(ages: &[i32]) -> Vec<AgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for &age in ages.iter() {
if age < 100 && age > 0 {
results.push(AgeOrError::Age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(AgeOrError::Error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
fn main() {
let v = get_results(&[1, -6, 7]);
let serialized = serde_json::to_string(&v).expect("Can't serialize");
println!("serialized: {}", serialized);
let deserialized: Vec<AgeOrError> =
serde_json::from_str(&serialized).expect("Can't deserialize");
println!("deserialized: {:?}", deserialized);
}
Note that in deserialization we can't reuse the automatically generated deserializers because:
deserialization is kind of streaming the fields to us, we can't peek into the stringified JSON representation and guess what it is;
we don't have access to the serde::de::Visitor implementations that Serde generates.
Also I did a shortcut and panicked on errors. In production code you'd want to return the proper Serde errors instead.
Another solution would be to make a merged structure with all fields optional, like this:
#[macro_use]
extern crate serde_derive; // 1.0.70
extern crate serde; // 1.0.70
extern crate serde_json; // 1.0.24
#[derive(Debug)]
pub struct MyError {
error: String,
}
#[derive(Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAgeOrError {
#[serde(skip_serializing_if = "Option::is_none")]
age: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
error: Option<String>,
}
impl MyAgeOrError {
fn from_age(age: MyAge) -> MyAgeOrError {
MyAgeOrError {
age: Some(age.age),
name: Some(age.name),
error: None,
}
}
fn from_error(error: MyError) -> MyAgeOrError {
MyAgeOrError {
age: None,
name: None,
error: Some(error.error),
}
}
}
fn get_results(ages: &[i32]) -> Vec<MyAgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for &age in ages.iter() {
if age < 100 && age > 0 {
results.push(MyAgeOrError::from_age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(MyAgeOrError::from_error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
fn main() {
let v = get_results(&[1, -6, 7]);
let serialized = serde_json::to_string(&v).expect("Can't serialize");
println!("serialized: {}", serialized);
let deserialized: Vec<MyAgeOrError> =
serde_json::from_str(&serialized).expect("Can't deserialize");
println!("deserialized: {:?}", deserialized);
}
I'd vouch for this one because it allows the Rust structure (e.g. MyAgeOrError) to match the layout of your JSON. That way the JSON layout becomes documented in the Rust code.
P.S. Lately I tend to delay the decoding of optional or dynamically typed JSON parts with the help of RawValue. It's tricky to serialize them though, because RawValue is a borrow. For instance, and to help with serialization, one can intern a RawValue, promoting it to the 'static lifetime:
use serde_json::value::{RawValue as RawJson};
fn intern_raw_json(raw_json: Box<RawJson>) -> &'static RawJson {
use parking_lot::Mutex;
use std::mem::transmute;
static BUF: Mutex<Vec<Pin<Box<RawJson>>>> = Mutex::new(Vec::new());
let buf = BUF.lock();
let raw_json: Pin<Box<RawJson>> = raw_json.into();
let pt: &'static RawJson = {
let pt: &RawJson = &*raw_json;
transmute(pt)
};
buf.push(raw_json);
pt
}
If performance is not an issue, then one can deserialize the dynamic parts into the Value.
Similarly, if using Value is an option, then custom deserialization can be simplified by implementing TryFrom<Value>.
Serde supports internally tagged and untagged enums as of version 0.9.6.
The following code shows an example of how this could be done by using an enum with the attribute #[serde(untagged)].
#[macro_use]
extern crate serde_derive; // 1.0.70
extern crate serde_json; // 1.0.24
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum AgeOrError {
Age(MyAge),
Error(MyError),
}
fn get_results(ages: Vec<i32>) -> Vec<AgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for age in ages {
if age < 100 && age > 0 {
results.push(AgeOrError::Age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(AgeOrError::Error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
fn main() {
let results = get_results(vec![1, -6, 7]);
let json = serde_json::to_string(&results).unwrap();
println!("{}", json);
}
The above code outputs the following JSON:
[{"age":1,"name":"The dude"},{"error":"-6 is invalid age"},{"age":7,"name":"The dude"}]
More information on Serde's enum representation can be found in the overview.

Retrieve datetime from mySQL database using Diesel

I can't retrieve datetime from a populated mySQL database using Rocket and Diesel.
Here is my model:
extern crate chrono;
use diesel::prelude::*;
use diesel::mysql::MysqlConnection;
use schema::chrisms;
use diesel::sql_types::Datetime;
use self::chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
#[derive(Serialize, Deserialize, Queryable)]
pub struct Chrisms {
pub entity_ekklesia_location_id: i32,
pub serie_number: Option<String>,
pub seat_number: Option<String>,
pub date: Datetime,
pub year: i32,
pub deleted: bool,
pub entity_chrism_location_id: Option<i32>,
pub entity_chrism_location_description: Option<String>,
pub entity_rel_mec_id: Option<i32>,
pub entity_rel_mec_description: Option<String>,
pub created_by_user_id: Option<i32>,
pub updated_by_user_id: Option<i32>,
pub deleted_by_user_id: Option<i32>,
pub created_at: Datetime,
pub updated_at: Datetime,
pub id: i32,
}
impl Chrisms {
pub fn read(connection: &MysqlConnection) -> Vec<Chrisms> {
chrisms::table.load::<Chrisms>(connection).unwrap()
}
}
My schema:
table! {
chrisms (id) {
entity_ekklesia_location_id -> Integer,
serie_number -> Nullable<Varchar>,
seat_number -> Nullable<Varchar>,
date -> Datetime,
year -> Integer,
deleted -> Bool,
entity_chrism_location_id -> Nullable<Integer>,
entity_chrism_location_description -> Nullable<Varchar>,
entity_rel_mec_id -> Nullable<Integer>,
entity_rel_mec_description -> Nullable<Varchar>,
created_by_user_id -> Nullable<Integer>,
updated_by_user_id -> Nullable<Integer>,
deleted_by_user_id -> Nullable<Integer>,
created_at -> Datetime,
updated_at -> Datetime,
id -> Integer,
}
}
This produces the errors:
1. the trait `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::Serialize` is not
implemented for `diesel::sql_types::Datetime`
-required by `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::ser::SerializeStruct::serialize_field`
2. the trait `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::Deserialize<'_>` is
not implemented for `diesel::sql_types::Datetime`
- required by `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::de::SeqAccess::next_element`
- required by `_IMPL_SERIALIZE_FOR_TemplateContext::_serde::de::MapAccess::next_value`
3. the trait `diesel::Queryable<diesel::sql_types::Datetime,
diesel::mysql::Mysql>` is not implemented for `diesel::sql_types::Datetime`
- required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, models::chrisms::Chrisms>` for `schema::chrisms::table`
How do I fix this? I tested a bunch of uses like diesel:mysql_types, rocket:config and so on, doesn't seem to be that the issue.
diesel Create/Read/Update/Delete example with datetime
Cargo.toml:
[dependencies]
diesel = { version = "1.4", features = ["sqlite", "chrono"] }
chrono = "0.4"
schema of users:
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
mod schema {
table! {
users (id) {
id -> Integer,
email -> Text,
created_at -> Timestamp,
}
}
}
mod models {
use super::schema::users;
#[derive(Queryable, Debug)]
pub struct User {
pub id: i32,
pub email: String,
/// deisel create must enable chrono feature
/// Timestamp without timezone, the memory align of Timestamp type in sqlite is same as libc::timeval?
pub created_at: chrono::NaiveDateTime,
}
#[derive(Insertable)]
#[table_name = "users"]
pub struct UserInsert {
pub email: String,
}
}
#[macro_use]
extern crate diesel;
use diesel::{
result::Error as DieselError, sql_types::BigInt, sqlite::SqliteConnection, Connection,
ExpressionMethods, QueryDsl, RunQueryDsl,
};
use models::{User, UserInsert};
use schema::users::dsl::{created_at, id, users};
fn create_user(conn: &SqliteConnection, new_user_form: UserInsert) -> Result<User, DieselError> {
// use sqlite(last_insert_rowid)/mysql(last_insert_id) to get current connection's last_insert_id
// use .order(id.desc()).last() will get the wrong id when multi db_connections insert at same time
no_arg_sql_function!(last_insert_rowid, BigInt);
diesel::insert_into(users)
.values(&new_user_form)
.execute(conn)?;
let new_user_id: i64 = diesel::select(last_insert_rowid).first(conn)?;
let last_insert_user: User = users.filter(id.eq(new_user_id as i32)).first(conn)?;
Ok(last_insert_user)
}
fn read_users(conn: &SqliteConnection) -> Result<Vec<User>, DieselError> {
Ok(users.load::<User>(conn)?)
}
fn update_user_created_at(conn: &SqliteConnection, user_id: i32) -> Result<(), DieselError> {
diesel::update(users.filter(id.eq(user_id)))
.set(created_at.eq(chrono::Utc::now().naive_utc()))
.execute(conn)?;
Ok(())
}
fn delete_user_by_user_id(conn: &SqliteConnection, user_id: i32) -> Result<(), DieselError> {
diesel::delete(users.filter(id.eq(user_id))).execute(conn)?;
Ok(())
}
/// diesel CRUD(Create, Read, Update, Delete) example with datetime
fn main() -> Result<(), DieselError> {
// TODO use r2d2 db_pool to enhance diesel performance
let conn = SqliteConnection::establish("file:db.sqlite").unwrap();
// clear all data before test
diesel::delete(users).execute(&conn)?;
let test_user_email = format!(
"test+{}#example.com",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs()
);
// CRUD - Create
println!("\nCRUD - Create");
let last_insert_user = create_user(
&conn,
UserInsert {
email: test_user_email,
},
)?;
dbg!(&last_insert_user);
// CRUD - Read
println!("\nCRUD - Read");
dbg!(read_users(&conn)?);
assert_eq!(read_users(&conn)?[0].id, last_insert_user.id);
// CRUD - Update
println!("\nCRUD - Update");
update_user_created_at(&conn, last_insert_user.id)?;
dbg!(read_users(&conn)?);
assert_ne!(read_users(&conn)?[0].created_at, last_insert_user.created_at);
// CRUD - Delete
println!("\nCRUD - Delete");
delete_user_by_user_id(&conn, last_insert_user.id)?;
dbg!(read_users(&conn)?);
assert!(read_users(&conn)?.is_empty());
Ok(())
}
Output Example:
CRUD - Create
[src/main.rs:85] &last_insert_user = User {
id: 1,
email: "test+1606720099#example.com",
created_at: 2020-11-30T07:08:19,
}
CRUD - Read
[src/main.rs:88] read_users(&conn)? = [
User {
id: 1,
email: "test+1606720099#example.com",
created_at: 2020-11-30T07:08:19,
},
]
CRUD - Update
[src/main.rs:93] read_users(&conn)? = [
User {
id: 1,
email: "test+1606720099#example.com",
created_at: 2020-11-30T07:08:19.386513,
},
]
CRUD - Delete
[src/main.rs:98] read_users(&conn)? = []

How can I use Serde with a JSON array with different objects for successes and errors?

I want to use Serde to create an array with error messages as well as proper objects:
extern crate serde; // 1.0.70
#[macro_use]
extern crate serde_derive; // 1.0.70
extern crate serde_json; // 1.0.24
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
fn get_results(ages: Vec<i32>) -> Vec<MyAge> {
let mut results = vec![];
for age in ages {
if age < 100 && age > 0 {
results.push(MyAge {
age: age,
name: String::from("The dude"),
});
} else {
results.push(MyError {
error: String::from(format!("{} is invalid age", age)),
});
}
}
results
}
When I pass in the Vec [1, -6, 7] I want to serialize to the JSON:
[{"age": 1, "name": "The dude"},{"error": "-6 is invalid age"},{"age": 7, "name": "The dude"}]
How do I do that? Knowing how to deserialize such an array would be nice as well.
Here's one way of doing that:
#[macro_use]
extern crate serde_derive; // 1.0.117
extern crate serde; // 1.0.117
extern crate serde_json; // 1.0.59
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Debug)]
enum AgeOrError {
Age(MyAge),
Error(MyError),
}
impl serde::Serialize for AgeOrError {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
&AgeOrError::Age(ref my_age) => serializer.serialize_some(my_age),
&AgeOrError::Error(ref my_error) => serializer.serialize_some(my_error),
}
}
}
enum AgeOrErrorField {
Age,
Name,
Error,
}
impl<'de> serde::Deserialize<'de> for AgeOrErrorField {
fn deserialize<D>(deserializer: D) -> Result<AgeOrErrorField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct AgeOrErrorFieldVisitor;
impl<'de> serde::de::Visitor<'de> for AgeOrErrorFieldVisitor {
type Value = AgeOrErrorField;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "age or error")
}
fn visit_str<E>(self, value: &str) -> Result<AgeOrErrorField, E>
where
E: serde::de::Error,
{
Ok(match value {
"age" => AgeOrErrorField::Age,
"name" => AgeOrErrorField::Name,
"error" => AgeOrErrorField::Error,
_ => panic!("Unexpected field name: {}", value),
})
}
}
deserializer.deserialize_any(AgeOrErrorFieldVisitor)
}
}
impl<'de> serde::Deserialize<'de> for AgeOrError {
fn deserialize<D>(deserializer: D) -> Result<AgeOrError, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(AgeOrErrorVisitor)
}
}
struct AgeOrErrorVisitor;
impl<'de> serde::de::Visitor<'de> for AgeOrErrorVisitor {
type Value = AgeOrError;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "age or error")
}
fn visit_map<A>(self, mut map: A) -> Result<AgeOrError, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut age: Option<i32> = None;
let mut name: Option<String> = None;
let mut error: Option<String> = None;
loop {
match map.next_key()? {
Some(AgeOrErrorField::Age) => age = map.next_value()?,
Some(AgeOrErrorField::Name) => name = map.next_value()?,
Some(AgeOrErrorField::Error) => error = map.next_value()?,
None => break,
}
}
if let Some(error) = error {
Ok(AgeOrError::Error(MyError { error: error }))
} else {
Ok(AgeOrError::Age(MyAge {
age: age.expect("!age"),
name: name.expect("!name"),
}))
}
}
}
fn get_results(ages: &[i32]) -> Vec<AgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for &age in ages.iter() {
if age < 100 && age > 0 {
results.push(AgeOrError::Age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(AgeOrError::Error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
fn main() {
let v = get_results(&[1, -6, 7]);
let serialized = serde_json::to_string(&v).expect("Can't serialize");
println!("serialized: {}", serialized);
let deserialized: Vec<AgeOrError> =
serde_json::from_str(&serialized).expect("Can't deserialize");
println!("deserialized: {:?}", deserialized);
}
Note that in deserialization we can't reuse the automatically generated deserializers because:
deserialization is kind of streaming the fields to us, we can't peek into the stringified JSON representation and guess what it is;
we don't have access to the serde::de::Visitor implementations that Serde generates.
Also I did a shortcut and panicked on errors. In production code you'd want to return the proper Serde errors instead.
Another solution would be to make a merged structure with all fields optional, like this:
#[macro_use]
extern crate serde_derive; // 1.0.70
extern crate serde; // 1.0.70
extern crate serde_json; // 1.0.24
#[derive(Debug)]
pub struct MyError {
error: String,
}
#[derive(Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAgeOrError {
#[serde(skip_serializing_if = "Option::is_none")]
age: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
error: Option<String>,
}
impl MyAgeOrError {
fn from_age(age: MyAge) -> MyAgeOrError {
MyAgeOrError {
age: Some(age.age),
name: Some(age.name),
error: None,
}
}
fn from_error(error: MyError) -> MyAgeOrError {
MyAgeOrError {
age: None,
name: None,
error: Some(error.error),
}
}
}
fn get_results(ages: &[i32]) -> Vec<MyAgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for &age in ages.iter() {
if age < 100 && age > 0 {
results.push(MyAgeOrError::from_age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(MyAgeOrError::from_error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
fn main() {
let v = get_results(&[1, -6, 7]);
let serialized = serde_json::to_string(&v).expect("Can't serialize");
println!("serialized: {}", serialized);
let deserialized: Vec<MyAgeOrError> =
serde_json::from_str(&serialized).expect("Can't deserialize");
println!("deserialized: {:?}", deserialized);
}
I'd vouch for this one because it allows the Rust structure (e.g. MyAgeOrError) to match the layout of your JSON. That way the JSON layout becomes documented in the Rust code.
P.S. Lately I tend to delay the decoding of optional or dynamically typed JSON parts with the help of RawValue. It's tricky to serialize them though, because RawValue is a borrow. For instance, and to help with serialization, one can intern a RawValue, promoting it to the 'static lifetime:
use serde_json::value::{RawValue as RawJson};
fn intern_raw_json(raw_json: Box<RawJson>) -> &'static RawJson {
use parking_lot::Mutex;
use std::mem::transmute;
static BUF: Mutex<Vec<Pin<Box<RawJson>>>> = Mutex::new(Vec::new());
let buf = BUF.lock();
let raw_json: Pin<Box<RawJson>> = raw_json.into();
let pt: &'static RawJson = {
let pt: &RawJson = &*raw_json;
transmute(pt)
};
buf.push(raw_json);
pt
}
If performance is not an issue, then one can deserialize the dynamic parts into the Value.
Similarly, if using Value is an option, then custom deserialization can be simplified by implementing TryFrom<Value>.
Serde supports internally tagged and untagged enums as of version 0.9.6.
The following code shows an example of how this could be done by using an enum with the attribute #[serde(untagged)].
#[macro_use]
extern crate serde_derive; // 1.0.70
extern crate serde_json; // 1.0.24
#[derive(Serialize, Deserialize, Debug)]
pub struct MyError {
error: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct MyAge {
age: i32,
name: String,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum AgeOrError {
Age(MyAge),
Error(MyError),
}
fn get_results(ages: Vec<i32>) -> Vec<AgeOrError> {
let mut results = Vec::with_capacity(ages.len());
for age in ages {
if age < 100 && age > 0 {
results.push(AgeOrError::Age(MyAge {
age: age,
name: String::from("The dude"),
}));
} else {
results.push(AgeOrError::Error(MyError {
error: format!("{} is invalid age", age),
}));
}
}
results
}
fn main() {
let results = get_results(vec![1, -6, 7]);
let json = serde_json::to_string(&results).unwrap();
println!("{}", json);
}
The above code outputs the following JSON:
[{"age":1,"name":"The dude"},{"error":"-6 is invalid age"},{"age":7,"name":"The dude"}]
More information on Serde's enum representation can be found in the overview.