Rust操作Josn数据及工作目录下多个应用程序维护示例

在学习Rust语言的时候,写的示例经常是一个rs文件,在练习的过程中经常会写多个应用程序示例,这样每个应用程序都需要单个编译,或者放在不同的目录下。那么有没有一个结构组织,可以同时编译多个应用程序,运行时指定某个程序即可呢。本文件以Json数据的包装解析,保存Josn数据到文件,读取Json文件数据的示例展示多应用程序操作。

首先新建一个workspace_json,然后新建一个Cargo.toml文件,内容如下:

复制代码
[package]
name = "workspace_json"
version = "0.1.0"
edition = "2024"

[[bin]]
name = "main"
path = "src/main.rs"

[dependencies]


# 在工作空间根目录运行
#cargo clean            #清理
#cargo build          # 编译所有 crate
#cargo build --bin main  # 只编译特定 crate

#运行
#cargo run --bin main

这里[[bin]]项目即是应用程序的配置,这里先编写一个main.rs程序,

1.Rust操作Json数据

1.1 动态创建json

复制代码
use serde_json::{Value, json};

//fn main() -> Result<(), Box<dyn std::error::Error>> {
fn main() {
    let data = r#"
        {
        "name": "王五",
        "age": 28,
        "hobbies": ["读书", "跑步"]
        }"#;
    //let v = serde_json::from_str(data)?;
    let result: Result<Value, _> = serde_json::from_str(data);
    match result {
        Ok(v) => {
            println!("{:?}", v);
            // 访问字段
            if let Some(name) = v.get("name") {
                println!("name = {}", name);
            }

            if let Some(age) = v.get("age") {
                println!("age = {}", age);
            }

            if let Some(hobbies) = v.get("hobbies").and_then(|h| h.as_array()) {
                println!("当前爱好: {:?}", hobbies);
            }
        },
        Err(e) => eprintln!("{}", e),
    }

    //使用 json! 宏动态创建 JSON
    let new_json = json!({
        "name": "赵六",
        "age": 32,
        "address": {
            "city": "北京",
            "street": "长安街"
        }
    });
    println!("first address: {}", new_json["address"][0]);
    // 转化为字符串输出
    println!("{}", new_json.to_string());
    //打印json对象
    println!("新建 JSON: {:?}", new_json);
}

//cargo run --bin main

编译运行:

复制代码
 PS F:\rustproject\workspace_json> cargo run
   Compiling proc-macro2 v1.0.106
   Compiling quote v1.0.44
   Compiling unicode-ident v1.0.24
   Compiling serde_core v1.0.228
   Compiling zmij v1.0.21
   Compiling serde v1.0.228
   Compiling serde_json v1.0.149
   Compiling itoa v1.0.17
   Compiling memchr v2.8.0
   Compiling syn v2.0.116
   Compiling serde_derive v1.0.228
   Compiling workspace_json v0.1.0 (F:\rustproject\workspace_json)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.88s
     Running `target\debug\main.exe`
Object {"age": Number(28), "hobbies": Array [String("读书"), String("跑步")], "name": String("王五")}
name = "王五"
age = 28
当前爱好: [String("读书"), String("跑步")]
first address: null
{"address":{"city":"北京","street":"长安街"},"age":32,"name":"赵六"}
新建 JSON: Object {"address": Object {"city": String("北京"), "street": String("长安街")}, "age": Number(32), "name": String("赵六
")}
PS F:\rustproject\workspace_json>

现在第一个应用程序已经运行OK。

1.2 json序列化

现在工作空间已经有一个应用程序了,现在添加第二个程序,在src目录下添加一个serialize.rs文件,功能 是json的序列化,这个时候就要在Cargo.toml文件中添加一个[[bin]]选项,完整的Cargo.toml配置文件如下:

复制代码
[package]
name = "workspace_json"
version = "0.1.0"
edition = "2024"

[[bin]]
name = "main"
path = "src/main.rs"

[[bin]]
name = "serialize"
path = "src/serialize.rs"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

serialize.rs文件:

复制代码
//Rust 结构体 → JSON 字符串(序列化)
use serde::Serialize;

#[derive(Serialize, Debug)]
struct Person{
    name: String,
    age: u8,
    email: String,
}

fn main() {
    let person = Person{
        name: "张三".to_string(),
        age: 30,
        email: "zhangsan@126.com".to_string(),
    };
    println!("person = {:?}", person);
    // 访问字段
    println!("name = {:?}", person.name);
    println!("age = {:?}", person.age);
    println!("email = {:?}", person.email);

    //let person2 = {};
    // 序列化为 JSON 字符串
    let result = serde_json::to_string(&person);  // result 是 Result<String, Error>
    match result {
        Ok(val) => {
            println!("序列化: {}", val);
        },
        Err(e) => eprintln!("{}", e),
    }

    // 也可以格式化为更美观的带缩进的字符串
    let pretty_json:Result<String, serde_json::Error> = serde_json::to_string_pretty(&person);
    println!("JSON Data serialize: {:?}", pretty_json);
    match pretty_json {
        Ok(val) => {
            println!("序列格式化: {}", val);
        },
        Err(e) => eprintln!("{}", e),
    }

}

//cargo run --bin serialize

编译cargo build:

复制代码
PS F:\rustproject\workspace_json> cargo build
   Compiling proc-macro2 v1.0.106
   Compiling quote v1.0.44
   Compiling unicode-ident v1.0.24
   Compiling serde_core v1.0.228
   Compiling zmij v1.0.21
   Compiling serde_json v1.0.149
   Compiling serde v1.0.228
   Compiling memchr v2.8.0
   Compiling itoa v1.0.17
   Compiling syn v2.0.116
   Compiling serde_derive v1.0.228
   Compiling workspace_json v0.1.0 (F:\rustproject\workspace_json)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 3.70s
PS F:\rustproject\workspace_json>

运行cargo run,这样运行就报错了,因为cargo build编译的时候就生成了两个应用程序,所以这里要指定一个程序运行,cargo run --bin serialize

复制代码
PS F:\rustproject\workspace_json> cargo run  
error: `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key.
available binaries: main, serialize
PS F:\rustproject\workspace_json> cargo run --bin serialize
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
     Running `target\debug\serialize.exe`
person = Person { name: "张三", age: 30, email: "zhangsan@126.com" }
name = "张三"
age = 30
email = "zhangsan@126.com"
序列化: {"name":"张三","age":30,"email":"zhangsan@126.com"}
JSON Data serialize: Ok("{\n  \"name\": \"张三\",\n  \"age\": 30,\n  \"email\": \"zhangsan@126.com\"\n}")
序列格式化: {
  "name": "张三",
  "age": 30,
  "email": "zhangsan@126.com"
}
PS F:\rustproject\workspace_json>

1.3 json反序列化

接着再在src目录下添加一个应用程序,然后在Cargo.toml文件中添加

复制代码
[[bin]]
name = "deserialize"
path = "src/deserialize.rs"

deserialize.rs文件:

复制代码
//JSON 字符串 → Rust 结构体(反序列化)
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Person{
    name: String,
    age: u8,
    email: String,
}

fn main() {
    //JSON 标准不允许在最后一个元素后面加逗号。
    let data = r#"
        {
        "name": "李四",
        "age": 25,
        "email": "zhangsn@126.com"
        }"#;

    let result: Result<Person, _> = serde_json::from_str(data);

    println!("person = {:?}", result);
    match result {
        Ok(val) => {
            println!("json = {:?}", val);
            // 访问字段
            println!("name = {:?}", val.name);
            println!("age = {:?}", val.age);
            println!("email = {:?}", val.email);
        },
        Err(e) => eprintln!("error: {}", e),
    }

    //错误结构示例   字段没对上Person
    let data = r#"
        {
        "name": "王五",
        "age": 28,
        "hobbies": ["读书", "跑步"]
        }"#;
    let result: Result<Person, _> = serde_json::from_str(data);
    match result {
        Ok(v) => {
            println!("{:?}", v);
        },
        Err(e) => eprintln!("error: {}", e),
    }

}

//cargo run --bin deserialize

编译运行:

复制代码
PS F:\rustproject\workspace_json> cargo run --bin deserialize
   Compiling workspace_json v0.1.0 (F:\rustproject\workspace_json)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s
     Running `target\debug\deserialize.exe`
person = Ok(Person { name: "李四", age: 25, email: "zhangsn@126.com" })
json = Person { name: "李四", age: 25, email: "zhangsn@126.com" }
name = "李四"
age = 25
email = "zhangsn@126.com"
error: missing field `email` at line 6 column 5
PS F:\rustproject\workspace_json>

2.保存JSON数据到文件,即写Json文件。

在src目录下添加子目录write_file里面放一个应用程序,然后在Cargo.toml文件中添加

复制代码
[[bin]]
name = "write_json"
path = "src/write_json/write_json_file.rs"

src/write_json/write_json_file.rs文件:

复制代码
//把JSON数据写到文件中
use std::fs;
use serde::Serialize;
use serde_json::Value;

#[derive(Serialize, Debug)]
struct Person{
    name: String,
    age: u8,
    email: String,
}

fn write_json_to_file(path: &str, data: &Value) -> Result<(), Box<dyn std::error::Error>> {
    let content = serde_json::to_string_pretty(data)?;
    fs::write(path, content)?;
    Ok(())
}
    
fn main() {
    let person = Person{
        name: "张三".to_string(),
        age: 30,
        email: "zhangsan@126.com".to_string(),
    };
    println!("person = {:?}", person);
    // 访问字段
    println!("name = {:?}", person.name);
    println!("age = {:?}", person.age);
    println!("email = {:?}", person.email);

    //let person2 = {};
    // 序列化为 JSON 字符串
    let result = serde_json::to_string(&person);  // result 是 Result<String, Error>
    match result {
        Ok(val) => {
            println!("序列化: {}", val);
        },
        Err(e) => eprintln!("{}", e),
    }
    
    // 把JSON数据写入到文件中
    let file_path = "file.json";
    // 将 Person 转换为 Value
    // 明确指定 Error 类型为 serde_json::Error
    //let person_value: Result<Value, serde_json::Error> = serde_json::to_value(&person);
    let person_value_result = serde_json::to_value(&person);
    match person_value_result {
        Ok(person_value) => {
            let result = write_json_to_file(file_path, &person_value);
            println!("result: {:?}", result);

            match result {
                Ok(val) => {
                    println!("{:?} 成功写入: {}", val, file_path);
                },
                Err(e) => eprintln!("{}", e),
            }
        },
        Err(e) => {
            eprintln!("序列化失败: {}", e);
        }
    }

}

//cargo run --bin write_json

编译运行

复制代码
 PS F:\rustproject\workspace_json> cargo run --bin write_json
   Compiling workspace_json v0.1.0 (F:\rustproject\workspace_json)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s
     Running `target\debug\write_json.exe`
person = Person { name: "张三", age: 30, email: "zhangsan@126.com" }
name = "张三"
age = 30
email = "zhangsan@126.com"
序列化: {"name":"张三","age":30,"email":"zhangsan@126.com"}
result: Ok(())
() 成功写入: file.json
PS F:\rustproject\workspace_json>

file.json文件内容:

3.从文件中读取JSON数据

也可以src目录下添加子目录read_file里面放一个应用程序,然后在Cargo.toml文件中添加

复制代码
[[bin]]
name = "read_file"
path = "src/read_file/read_json_file.rs"

read_json_file.rs文件:

复制代码
//从文件中读取JSON数据
use std::fs;
use serde::{Serialize, Deserialize};
use serde_json::Value;

#[derive(Serialize, Deserialize, Debug)]
struct Person{
    name: String,
    age: u8,
    email: String,
}

fn read_json_from_file(path: &str) -> Result<Value, Box<dyn std::error::Error>> {
    let content = fs::read_to_string(path)?;
    let v: Value = serde_json::from_str(&content)?;
    Ok(v)
}
    
fn main() {
    let file_path = "file.json";
    let result = read_json_from_file(file_path);

    //JSON 字符串 → Rust 结构体(反序列化)
    match result {
        Ok(val) => {
            println!("反序列化: {}", val);
            // 从 Value 反序列化为 Person
            let person_result: Result<Person, _> = serde_json::from_value(val);
            println!("person = {:?}", person_result);
            match person_result {
                Ok(person) => {
                    println!("反序列化成功:  {:?}", person);
                    // 访问字段
                    println!("name = {:?}", person.name);
                    println!("age = {:?}", person.age);
                    println!("email = {:?}", person.email);
                },
                Err(e) => eprintln!("error: {}", e),
            }
        },
        Err(e) => eprintln!("{}", e),
    }

    //-------------------------------------------
    let person = Person{
        name: "何明明".to_string(),
        age: 32,
        email: "hemingming@126.com".to_string(),
    };
    println!("person = {:?}", person);
    // 访问字段
    println!("name = {:?}", person.name);
    println!("age = {:?}", person.age);
    println!("email = {:?}", person.email);

}

//cargo run --bin read_json

编译运行

复制代码
 PS F:\rustproject\workspace_json> cargo run --bin read_json
   Compiling workspace_json v0.1.0 (F:\rustproject\workspace_json)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s
     Running `target\debug\read_json.exe`
反序列化: {"age":30,"email":"zhangsan@126.com","name":"张三"}
person = Ok(Person { name: "张三", age: 30, email: "zhangsan@126.com" })
反序列化成功:  Person { name: "张三", age: 30, email: "zhangsan@126.com" }
name = "张三"
age = 30
email = "zhangsan@126.com"
person = Person { name: "何明明", age: 32, email: "hemingming@126.com" }
name = "何明明"
age = 32
email = "hemingming@126.com"
PS F:\rustproject\workspace_json> 

完整的Cargo.toml文件如下:

复制代码
 [package]
name = "workspace_json"
version = "0.1.0"
edition = "2024"

[[bin]]
name = "main"
path = "src/main.rs"

[[bin]]
name = "serialize"
path = "src/serialize.rs"

[[bin]]
name = "deserialize"
path = "src/deserialize.rs"

[[bin]]
name = "read_json"
path = "src/read_json/read_json_file.rs"

[[bin]]
name = "write_json"
path = "src/write_json/write_json_file.rs"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

# 在工作空间根目录运行
#cargo clean            #清理
#cargo build          # 编译所有 crate
#cargo build --bin main  # 只编译特定 crate

#运行
#cargo run --bin main

工作目录结构如下:

这种结构的好处理的,多个程序生成在同一个target目录下,节省磁盘空间,尤其是引用到第三方库时,如果一个程序一个target目录会生成几G的临时文件,非常占空间。

相关推荐
Source.Liu4 小时前
【rust-i18n】readme.md文件
rust·rust-i18n
锅包一切1 天前
在蓝桥杯边练边学Rust:2.原生类型
开发语言·学习·蓝桥杯·rust
@atweiwei1 天前
Rust 实现 LangChain
开发语言·算法·rust·langchain·llm·agent·rag
Hello.Reader1 天前
Tauri 开发环境 Prerequisites 桌面 + 移动端)
rust·tauri
Source.Liu1 天前
【rust-i18n】简介
rust·rust-i18n
鸿乃江边鸟1 天前
Spark Datafusion Comet 向量化Rust Native--Native算子ScanExec以及涉及到的Selection Vectors
大数据·rust·spark·arrow
Hello.Reader1 天前
Tauri 用“系统 WebView + 原生能力”构建更小更快的跨平台应用
rust·tauri
RoyLin2 天前
Rust 编写的 40MB 大小 MicroVM 运行时,完美替代 Docker 作为 AI Agent Sandbox
后端·架构·rust
班公湖里洗过脚2 天前
《通过例子学Rust》第20章 标准库更多介绍
rust