• 【rust/egui】(十一)使用rfd选择文件并使用serde_json进行序列化


    说在前面

    • rust新手,egui没啥找到啥教程,这里自己记录下学习过程
    • 环境:windows11 22H2
    • rust版本:rustc 1.71.1
    • egui版本:0.22.0
    • eframe版本:0.22.0
    • 上一篇:这里

    rfd-Rusty File Dialogs

    • 一个跨平台的本地文件选择库,支持的平台:
      • Windows
      • macOS
      • Linux & BSDs (GTK3 or XDG Desktop Portal)
      • WASM32 (async only)
    • 让我们来看看使用:
      if ui.button("open file").clicked() {
      	if let Some(path) = rfd::FileDialog::new().pick_file() {
          	self.picked_path = Some(path.display().to_string());
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      在这里插入图片描述
    • 还可以添加文件后缀筛选:
      if ui.button("open file").clicked() {
      	if let Some(path) = rfd::FileDialog::new().add_filter("text", &["txt", "rs"]).pick_file() {
          	self.picked_path = Some(path.display().to_string());
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      在这里插入图片描述
    • 有了文件路径之后,我们就可以通过标准的文件库进行读写了

    serde_json

    • 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);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
    • 在我们的例子中,首先定义下结构体:

      #[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,
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    • 然后是初始化代码:

      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)
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    • 我们的json数据如下:

      {
      	"name": "test",
      	"path": "C:\\Users\\b3.txt",
      	"description": null,
      	"data": {
      		"version": "0.0.1",
      		"scope": "project",
      		"selectedTree": "045b5abc-aef7-4909-8d16-5797ebb270e9",
      	}
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • 运行我们的代码,选择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
      
      • 1
      • 2
      • 3

      这是因为对于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,
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      description修改为枚举Value

      pub enum Value {
          Null,
          Bool(bool),
          Number(Number),
          String(String),
          Array(Vec<Value>),
          Object(Map<String, Value>),
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 再次运行代码,发现又报错了:

      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
      
      • 1
      • 2
      • 3

      这是因为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,
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      这样就可以指定序列化与反序列化时的名称为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)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    参考

  • 相关阅读:
    【华为OD机试真题 python】 水仙花数【2022 Q4 | 100分】
    019 Linux tcpdump 抓包案例入门可真简单啊?
    PCL入门1之点云读取及可视化
    hadoop学习笔记-centos环境
    【算法系列 | 7】深入解析查找算法之—布隆过滤器
    VScode仿Ubuntu颜色,配色方案
    类的加载(也叫类的初始化)和对象初始化
    北斗导航 | GNSS观测模型(公式推导)
    DPD(Digital Pre-Distortion,数字预失真)
    使用GPT-4生成训练数据微调GPT-3.5 RAG管道
  • 原文地址:https://blog.csdn.net/qq_33446100/article/details/132918882