I'm trying to serialise JSON values from a serde_json::Map
into a SQLite database. I would like to use multiple data types in the Map
and have them converted into the appropriate SQLite datatypes.
The map is created in collect_values
and is passed to the write_record
function. The new_db
function creates a rustqlite::Connection
context that is passed to write_record
However when I try to insert the values from the map, I get this error
error[E0277]: the trait bound `serde_json::value::Value: rusqlite::types::to_sql::ToSql` is not satisfied
--> src/main.rs:51:9
|
51 | / params![
52 | | &values.get("TEST-KEY-1").unwrap_or(&missing_value),
53 | | &values.get("TEST-KEY-2").unwrap_or(&missing_value)
54 | | ],
| |_________^ the trait `rusqlite::types::to_sql::ToSql` is not implemented for `serde_json::value::Value`
|
= note: required because of the requirements on the impl of `rusqlite::types::to_sql::ToSql` for `&serde_json::value::Value`
= note: required because of the requirements on the impl of `rusqlite::types::to_sql::ToSql` for `&&serde_json::value::Value`
= note: required for the cast to the object type `dyn rusqlite::types::to_sql::ToSql`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Do I need to implement the serialiser manually? I thought rusqlite's types
module already has this done.
Cargo.toml
[package]
name = "sqlite-min-example"
version = "0.1.0"
authors = ["test"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rusqlite = "0.23.1"
serde_json = "1.0"
serde = {version = "1.0.113", default-features = false}
main.rs
use rusqlite::{params, Connection, Result};
use serde_json::json;
use serde_json::map::Map;
fn main() {
println!("Opening connection");
let conn = new_db();
match conn {
Ok(ctx) => {
let mp = collect_values();
let res = insert_record(&mp, &ctx);
}
Err(e) => {
eprintln!("{}", e);
}
}
}
pub fn new_db() -> Result<rusqlite::Connection> {
let conn = Connection::open("test.db")?;
//let conn = Connection::open_in_memory()?;
conn.execute(
"CREATE TABLE IF NOT EXISTS testdb (
field1 INTEGER,
field2 INTEGER
)",
params![],
)?;
// return the new connection context (object)
Ok(conn)
}
pub fn insert_record(
values: &serde_json::map::Map<std::string::String, serde_json::value::Value>,
conn: &rusqlite::Connection,
) -> Result<()> {
// Insert this if we can't find a value for a key for some reason...
let missing_value = json!("MISSINGVAL");
conn.execute(
"INSERT INTO testdb
(
field1,
field2
)
VALUES (
?1, ?2
)",
params![
&values.get("TEST-KEY-1").unwrap_or(&missing_value),
&values.get("TEST-KEY-2").unwrap_or(&missing_value)
],
)?;
// return any errors that occured
Ok(())
}
pub fn collect_values() -> serde_json::map::Map<std::string::String, serde_json::value::Value> {
// Take in the Modbus context and return a map of keys (field names) and their associated values
let mut map = Map::new();
map.insert("TEST-KEY-1".to_string(), json!(1234));
map.insert("TEST-KEY-2".to_string(), json!(5678));
return map;
}
Add the appropriate feature to rusqlite in your Cargo.toml:
rusqlite = { version = "0.23.1", features = ["serde_json"] }
See also: