-
json
序列化与反序列化库
-
在之前的文章中我们已经初步接触了serde
相关知识,这里我们来看看其他内容
-
在我们获取到文件路径后,我们就可以读取json文件了,同时,对于比较大的文件,serde_json
也提供了from_reader
的方法:
use serde::Deserialize;
use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
#[derive(Deserialize, Debug)]
struct User {
fingerprint: String,
location: String,
}
fn read_user_from_file<P: AsRef<Path>>(path: P) -> Result<User, Box<dyn Error>> {
// 使用只读方式读取文件 并使用buffer存储
let file = File::open(path)?;
let reader = BufReader::new(file);
// 反序列化json数据
let u = serde_json::from_reader(reader)?;
// 返回
Ok(u)
}
fn main() {
let u = read_user_from_file("test.json").unwrap();
println!("{:#?}", u);
}
-
在我们的例子中,首先定义下结构体:
#[derive(serde::Deserialize, serde::Serialize)]
pub struct WorkSpace {
pub name: String,
pub path: String,
pub description: String,
pub data: Project,
}
#[derive(serde::Deserialize, serde::Serialize)]
pub struct Project {
version: String,
scope: String,
selected_tree: String,
}
-
然后是初始化代码:
impl WorkSpace {
pub fn new(path: String) -> Self {
Self::from_file(path).unwrap()
}
fn from_file<P: AsRef<Path>>(path: P) -> Result<WorkSpace, Box<dyn Error>> {
// 使用只读方式读取文件 并使用buffer存储
let file = File::open(path)?;
let reader = BufReader::new(file);
let u = serde_json::from_reader(reader)?;
Ok(u)
}
}
-
我们的json数据如下:
{
"name": "test",
"path": "C:\\Users\\b3.txt",
"description": null,
"data": {
"version": "0.0.1",
"scope": "project",
"selectedTree": "045b5abc-aef7-4909-8d16-5797ebb270e9",
}
}
-
运行我们的代码,选择json文件,发现报错了:
thread 'main' panicked at
'called `Result::unwrap()` on an `Err` value: Error("invalid type: null, expected a string", line: xxx, column: 17)',
src\project.rs:18:32
这是因为对于WorkSpace.description
,我们定义的String
类型,但是我们的json数据中却是null
,匹配不上,要解决这个问题,我们可以这样:
#[derive(serde::Deserialize, serde::Serialize)]
pub struct WorkSpace {
pub name: String,
pub path: String,
pub description: serde_json::Value,
pub data: Project,
}
将description
修改为枚举Value
pub enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}
-
再次运行代码,发现又报错了:
thread 'main' panicked at
'called `Result::unwrap()` on an `Err` value: Error("missing field `selected_tree`", line: 245515, column: 2)',
src\project.rs:18:32
这是因为Project.selected_tree
的默认反序列化名称为selected_tree
,而在我们的json
数据中为selectedTree
,这时我们可以这样处理:
#[derive(serde::Deserialize, serde::Serialize)]
pub struct Project {
version: String,
scope: String,
#[serde(rename(serialize = "selectedTree", deserialize = "selectedTree"))]
selected_tree: String,
}
这样就可以指定序列化与反序列化时的名称为selectedTree
-
然后我们来试试序列化并保存文件,同样可以使用I/O stream
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), serde_json::Error> {
let file = File::options().create_new(true).write(true).open(path).unwrap();
let writer = BufWriter::new(file);
serde_json::to_writer_pretty(writer, self)
}