33 个版本 (破坏性更新)
新版本 0.36.0 | 2024 年 8 月 22 日 |
---|---|
0.35.0 | 2024 年 2 月 19 日 |
0.34.0 | 2023 年 11 月 14 日 |
0.33.1 | 2023 年 5 月 18 日 |
0.11.0 | 2017 年 6 月 2 日 |
#154 在 编码
12,738 每月下载量
在 15 个 crate 中使用 15 (12 直接使用)
68KB
1.5K SLoC
serde_rusqlite
文档
查看 完整文档
使用方法
将以下内容添加到您的 Cargo.toml
[dependencies]
serde_rusqlite = "0.36.0"
Serde Rusqlite
此 crate 提供了连接 serde 和 rusqlite 的便利函数。有了这些函数,您可以将 rusqlite 的 Row
反序列化为 serde 的 Deserialize
类型,并将实现 Serialize
的类型序列化为 rusqlite 期望的位置参数或命名参数。
仅支持从结构体和映射中序列化命名绑定参数,因为其他 serde 类型缺少列名信息。同样,仅支持从元组、序列和原始非迭代类型中序列化位置绑定参数。在后一种情况下,结果将是单元素向量。每个序列化的字段或元素都必须实现 rusqlite::types::ToSql
。
对于反序列化,您可以使用两个函数家族:from_*()
和 from_*_with_columns()
。最常用的是前者。后者允许您为需要但未提供列名的类型指定列名,这包括不同的 Map
类型,如 HashMap
。将列指定为反序列化到例如结构体不会产生任何效果,因为结构体的字段列表在任何情况下都会被使用。
SQLite只支持5种类型:NULL
(None
)、INTEGER
(i64
)、REAL
(f64
)、TEXT
(String
)和BLOB
(Vec<u8>
)。对应的Rust类型放在括号内。
某些类型需要复杂处理,下面将进行描述。
-
由于SQLite的限制,当无法用
i64
表示时,u64
的序列化将失败。 -
简单的
enum
将被序列化为字符串,因此enum Gender { M, F, }
数据库中将有两个可能的
TEXT
选项:"M"和"F"。也支持从TEXT
反序列化为enum
。 -
bool
被序列化为整数0或1,可以从INTEGER
和REAL
反序列化,其中0和0.0是false
,其他任何内容都是true
。 -
f64
和f32
的NaN
值被序列化为NULL
。当反序列化此类值时,Option<f64>
将具有值None
,而f64
将具有值NaN
。同样适用于f32
。 -
Bytes
和ByteBuf从
serde_bytes
支持作为处理BLOB
的优化方式。 -
unit
序列化为NULL
。 -
只有
sequence
的u8
被序列化和反序列化,使用数据库中的BLOB
类型。尽管如此,对于此类字段,使用来自serde_bytes
的Bytes
和ByteBuf
会更优化。 -
unit_struct
序列化为struct
名称作为TEXT
,在反序列化时将检查struct
名称是否与数据库中的字符串相匹配。
示例
use serde_derive::{Deserialize, Serialize};
use serde_rusqlite::*;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Example {
id: i64,
name: String,
}
let connection = rusqlite::Connection::open_in_memory().unwrap();
connection.execute("CREATE TABLE example (id INT, name TEXT)", []).unwrap();
// using structure to generate named bound query arguments
let row1 = Example { id: 1, name: "first name".into() };
connection.execute("INSERT INTO example (id, name) VALUES (:id, :name)", to_params_named(&row1).unwrap().to_slice().as_slice()).unwrap();
// and limiting the set of fields that are to be serialized
let row2 = Example { id: 10, name: "second name".into() };
connection.execute("INSERT INTO example (id, name) VALUES (2, :name)", to_params_named_with_fields(&row2, &["name"]).unwrap().to_slice().as_slice()).unwrap();
// using tuple to generate positional bound query arguments
let row2 = (3, "third name");
connection.execute("INSERT INTO example (id, name) VALUES (?, ?)", to_params(&row2).unwrap()).unwrap();
// deserializing using query() and from_rows(), the most efficient way
let mut statement = connection.prepare("SELECT * FROM example").unwrap();
let mut res = from_rows::<Example>(statement.query([]).unwrap());
assert_eq!(res.next().unwrap().unwrap(), row1);
assert_eq!(res.next().unwrap().unwrap(), Example { id: 2, name: "second name".into() });
// deserializing using query_and_then() and from_row(), incurs extra overhead in from_row() call
let mut statement = connection.prepare("SELECT * FROM example").unwrap();
let mut rows = statement.query_and_then([], from_row::<Example>).unwrap();
assert_eq!(rows.next().unwrap().unwrap(), row1);
assert_eq!(rows.next().unwrap().unwrap(), Example { id: 2, name: "second name".into() });
// deserializing using query_and_then() and from_row_with_columns(), better performance than from_row()
let mut statement = connection.prepare("SELECT * FROM example").unwrap();
let columns = columns_from_statement(&statement);
let mut rows = statement.query_and_then([], |row| from_row_with_columns::<Example>(row, &columns)).unwrap();
assert_eq!(rows.next().unwrap().unwrap(), row1);
assert_eq!(rows.next().unwrap().unwrap(), Example { id: 2, name: "second name".into() });
// deserializing using query() and from_rows_ref()
let mut statement = connection.prepare("SELECT * FROM example").unwrap();
let mut rows = statement.query([]).unwrap();
{
// only first record is deserialized here
let mut res = from_rows_ref::<Example>(&mut rows);
assert_eq!(res.next().unwrap().unwrap(), row1);
}
// the second record is deserialized using the original Rows iterator
assert_eq!(from_row::<Example>(&rows.next().unwrap().unwrap()).unwrap(), Example { id: 2, name: "second name".into() });
许可:MIT OR Apache-2.0
依赖项
~22MB
~425K SLoC