在学习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的临时文件,非常占空间。