欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
AtomGit 仓库地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_rust_cargo

本文讲解鸿蒙 PC 端 Rust 开发环境搭建,鸿蒙基于 musl 库、强制二进制签名,无法直接使用通用 Linux 编译产物。需借助鸿蒙专属包管理器 Harmonybrew,提供两套编译方案:方案一安装 llvm-gcc-compat,零配置开箱即用;方案二仅安装 ohos-sdk,需手动配置 Cargo 链接器,二者都依托 ohos-sdk 完成自动签名编译。

可以来参考一下这个文章搭建环境OpenHarmony 鸿蒙 PC + CodeArts IDE 实现 Rust开发完整开发环境搭建指南


一、两个库分别是什么、作用

1. serde

Rust 行业标准通用序列化/反序列化框架,支持 JSON、YAML、Toml、Bincode 等几乎所有格式。

  • 核心功能:把 Rust 结构体、枚举、基础类型转成字节/字符串(序列化);把字符串/字节还原成 Rust 变量(反序列化)
  • serde/derive 特性:提供 #[derive(Serialize, Deserialize)] 派生宏,自动为结构体生成序列化代码,不用手写转换逻辑
  • 支持自定义字段名、忽略字段、默认值、嵌套结构体、数组、枚举、泛型
  • 无运行时反射,编译期生成代码,性能极高

2. serde_json

serde 的 JSON 专用实现,负责 JSON 字符串与 Rust 类型互转:

  1. 序列化:Rust struct → JSON 字符串(紧凑/带格式化两种输出)
  2. 反序列化:JSON 字符串 → Rust struct / Value 动态对象
  3. 动态操作无固定结构 JSON:serde_json::Value(Object/Array/Number/String/Bool/Null)

适用开发场景

  1. Web 后端(Axum/Rocket)HTTP 请求体、返回 JSON 响应
  2. 读取/写入 JSON 配置文件
  3. 接口调用:发送 JSON 请求、解析第三方接口返回 JSON
  4. 缓存、消息队列 JSON 数据编解码
  5. 动态处理未知结构 JSON(日志、第三方数据)

二、安装依赖

# serde 开启 derive 派生宏特性,同时安装 serde_json
cargo add serde --features derive
cargo add serde_json

自动写入 Cargo.toml

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

请添加图片描述

三、完整无报错 main.rs

覆盖:固定结构体序列化/反序列化、格式化输出、自定义JSON字段名、忽略字段、动态Value操作、嵌套结构体、数组列表。

use serde::{Deserialize, Serialize};
use serde_json::{json, to_string_pretty, from_str, Value};

// 1. 基础用户结构体,派生序列化、反序列化
#[derive(Debug, Serialize, Deserialize)]
struct User {
    // json 内字段名改为 user_name,而非默认 username
    #[serde(rename = "user_name")]
    username: String,
    age: u8,
    // 序列化时忽略此字段,反序列化不存在则用默认值
    #[serde(skip_serializing, default)]
    password: String,
    is_vip: bool,
}

// 2. 嵌套结构体演示
#[derive(Debug, Serialize, Deserialize)]
struct Order {
    order_id: String,
    price: f64,
    buyer: User,
    goods_list: Vec<String>,
}

fn main() {
    // ===================== 一、结构体序列化为 JSON 字符串 =====================
    println!("===== 1. 结构体序列化 JSON =====");
    let user = User {
        username: "zhangsan2026".to_string(),
        age: 24,
        password: "123456".to_string(),
        is_vip: true,
    };
    // 格式化带换行缩进的JSON
    let user_json = to_string_pretty(&user).unwrap();
    println!("用户JSON:\n{}", user_json);

    // 嵌套结构体
    let order = Order {
        order_id: "ORD0618001".to_string(),
        price: 199.99,
        buyer: user,
        goods_list: vec!["机械键盘".to_string(), "无线鼠标".to_string()],
    };
    let order_json = to_string_pretty(&order).unwrap();
    println!("\n订单嵌套JSON:\n{}", order_json);

    // ===================== 二、JSON字符串反序列化为结构体 =====================
    println!("===== 2. JSON 反序列化结构体 =====");
    let json_text = r#"{
        "user_name": "lisi",
        "age": 20,
        "is_vip": false
    }"#;
    let parse_user: User = from_str(json_text).unwrap();
    println!("解析后的用户: {:?}", parse_user);
    // password 被忽略,使用默认空字符串
    println!("密码字段: {}", parse_user.password);

    // ===================== 三、动态构造JSON(无固定结构体,json!宏) =====================
    println!("\n===== 3. json! 宏快速构造动态JSON =====");
    let dynamic_json = json!({
        "code": 200,
        "msg": "success",
        "data": {
            "list": [10, 20, 30],
            "total": 100
        }
    });
    // Value 转格式化字符串
    let dyn_str = to_string_pretty(&dynamic_json).unwrap();
    println!("动态构造JSON:\n{}", dyn_str);

    // 读取动态JSON内部字段
    let code = dynamic_json["code"].as_u64().unwrap();
    let total = dynamic_json["data"]["total"].as_u64().unwrap();
    println!("响应code: {}, 数据总数: {}", code, total);

    // ===================== 四、动态Value 类型操作未知JSON =====================
    println!("\n===== 4. Value 动态修改JSON字段 =====");
    let mut val: Value = json!({ "count": 1 });
    // 修改数字字段
    val["count"] = json!(100);
    // 新增数组
    val["tags"] = json!(["rust", "serde", "json"]);
    println!("修改后Value:\n{}", to_string_pretty(&val).unwrap());
}

请添加图片描述

四、运行命令

cargo run

serde 是 Rust 生态标准序列化/反序列化框架,serde_json 是针对 JSON 的实现,用来实现 结构体 ↔ JSON 字符串 互转、动态JSON对象操作,后端接口、配置文件、网络报文必备。

前置 Cargo.toml 依赖

[dependencies]
# 序列化核心,derive 开启派生宏 Serialize/Deserialize
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

导入包说明

use serde::{Deserialize, Serialize};
use serde_json::{json, to_string_pretty, from_str, Value};
  1. Serialize:特征,结构体转JSON
  2. Deserialize:特征,JSON转回结构体
  3. json!:宏,快速构建无固定结构的动态JSON对象
  4. to_string_pretty:格式化带缩进换行的JSON字符串(打印调试用)
    配套还有 to_string() 压缩无空格JSON(网络传输用)
  5. from_str:JSON字符串 → 结构体 / Value
  6. Value:动态JSON枚举类型,代表任意JSON(对象/数组/数字/字符串/null)

一、结构体定义 + serde 属性注解

1. User 基础结构体

#[derive(Debug, Serialize, Deserialize)]
struct User {
    #[serde(rename = "user_name")]
    username: String,
    age: u8,
    #[serde(skip_serializing, default)]
    password: String,
    is_vip: bool,
}

1)派生宏 Serialize, Deserialize

自动为结构体实现序列化、反序列化逻辑,省去手写转换代码。

2)#[serde(rename = "user_name")] 字段重命名

Rust 字段名是 username,但 JSON 里键名要叫 user_name

  • 序列化:username → json 键 user_name
  • 反序列化:json 里 user_name 自动映射到 username

3)#[serde(skip_serializing, default)] 复合注解

两个配置同时生效:

  1. skip_serializing序列化时忽略此字段
    把 User 转 JSON 时,不会输出 password 字段(保护密码不返回前端)
  2. default:反序列化时,如果JSON不存在该字段,使用类型默认值
    String 默认空字符串,所以示例里没传password,解析后 password = ""

2. Order 嵌套结构体

#[derive(Debug, Serialize, Deserialize)]
struct Order {
    order_id: String,
    price: f64,
    buyer: User,
    goods_list: Vec<String>,
}

serde 天然支持嵌套结构体、Vec数组,无需额外配置:

  • buyer: User:JSON中是嵌套对象
  • goods_list: Vec<String>:JSON中是字符串数组

二、模块1:结构体序列化为 JSON 字符串

1. User 序列化

let user = User {
    username: "zhangsan2026".to_string(),
    age: 24,
    password: "123456".to_string(),
    is_vip: true,
};
let user_json = to_string_pretty(&user).unwrap();
println!("用户JSON:\n{}", user_json);

执行逻辑

to_string_pretty(&T):接收实现 Serialize 的结构体引用,输出带缩进美化JSON。
根据注解规则:

  1. 字段 username → json 键 user_name
  2. passwordskip_serializing 忽略,输出的JSON没有password字段

输出JSON片段:

{
  "user_name": "zhangsan2026",
  "age": 24,
  "is_vip": true
}

2. 嵌套 Order 序列化

let order = Order {
    order_id: "ORD0618001".to_string(),
    price: 199.99,
    buyer: user,
    goods_list: vec!["机械键盘".to_string(), "无线鼠标".to_string()],
};
let order_json = to_string_pretty(&order).unwrap();

JSON会生成嵌套对象,buyer 内部结构完全复用 User 的序列化规则,数组正常渲染。


三、模块2:JSON字符串反序列化为结构体

let json_text = r#"{
    "user_name": "lisi",
    "age": 20,
    "is_vip": false
}"#;
let parse_user: User = from_str(json_text).unwrap();
println!("解析后的用户: {:?}", parse_user);
println!("密码字段: {}", parse_user.password);

核心逻辑

from_str::<T>(json字符串):将文本JSON转换成目标结构体 T,返回 Result<T, Error>unwrap() 简化错误处理。

对应注解规则生效

  1. JSON键 user_name 匹配结构体 username
  2. JSON 里没有 password 字段#[serde(default)] 生效,自动填充空字符串 ""

关键注意

如果去掉 default,JSON缺少password字段时会直接解析报错;加了default则兼容缺省字段。


四、模块3:json! 宏 快速构造动态JSON(无固定结构体)

适用场景

接口返回统一格式(code/msg/data)、临时拼接JSON、结构不固定无法提前定义struct。

let dynamic_json = json!({
    "code": 200,
    "msg": "success",
    "data": {
        "list": [10, 20, 30],
        "total": 100
    }
});

json!{} 宏直接写类JS对象语法,返回 serde_json::Value 类型。

读取内部字段

let code = dynamic_json["code"].as_u64().unwrap();
let total = dynamic_json["data"]["total"].as_u64().unwrap();

Value 像数组/Map一样用 [] 访问嵌套key;
as_u64() / as_str() / as_bool() 安全提取对应类型,不存在或类型不匹配返回None。

转字符串

to_string_pretty(&dynamic_json) 把 Value 转为打印用格式化字符串。


五、模块4:Value 动态修改、新增JSON字段

Value 是可变动态JSON容器,适合解析未知结构报文、运行时增删改字段。

let mut val: Value = json!({ "count": 1 });
val["count"] = json!(100);
val["tags"] = json!(["rust", "serde", "json"]);

操作说明

  1. 必须声明 mut 可变
  2. 赋值右侧必须也是 Value 类型,用 json!() 包装数字、数组、对象
  3. 直接 val["新key"] 赋值即可新增字段,覆盖原有key实现修改

打印输出:

{
  "count": 100,
  "tags": [
    "rust",
    "serde",
    "json"
  ]
}

六、核心工具函数区分

函数 作用 使用场景
to_string(&T) 压缩无空格JSON HTTP接口传输,节省流量
to_string_pretty(&T) 带换行缩进美化JSON 日志打印、调试查看
from_str::<T>(text) JSON字符串 → 结构体 已知报文结构,强类型解析
json!{} 构建Value动态对象 结构不固定、临时组装返回体

七、常用 serde 注解拓展(补充示例里用到的)

  1. #[serde(rename = "xxx")] 字段名映射
  2. #[serde(skip_serializing)] 序列化忽略
  3. #[serde(skip_deserializing)] 反序列化忽略
  4. #[serde(default)] 缺失字段填充类型默认值
  5. #[serde(rename_all = "snake_case")] 批量自动下划线命名(结构体上)

八、两种开发模式选择

  1. 强类型结构体模式(示例前两部分)
    接口入参、数据库实体、固定报文;编译期校验字段,类型安全,推荐业务主流程使用。
  2. Value动态模式(后两部分)
    第三方未知JSON、动态配置、统一返回包装体;无编译校验,运行时可能类型错误,适合临时、弱结构数据。

九、完整程序输出预览

===== 1. 结构体序列化 JSON =====
用户JSON:
{
  "user_name": "zhangsan2026",
  "age": 24,
  "is_vip": true
}

订单嵌套JSON:
{
  "order_id": "ORD0618001",
  "price": 199.99,
  "buyer": {
    "user_name": "zhangsan2026",
    "age": 24,
    "is_vip": true
  },
  "goods_list": [
    "机械键盘",
    "无线鼠标"
  ]
}

===== 2. JSON 反序列化结构体 =====
解析后的用户: User { username: "lisi", age: 20, password: "", is_vip: false }
密码字段: 

===== 3. json! 宏快速构造动态JSON =====
动态构造JSON:
{
  "code": 200,
  "msg": "success",
  "data": {
    "list": [
      10,
      20,
      30
    ],
    "total": 100
  }
}
响应code: 200, 数据总数: 100

===== 4. Value 动态修改JSON字段 =====
修改后Value:
{
  "count": 100,
  "tags": [
    "rust",
    "serde",
    "json"
  ]
}

五、核心API与标签详细说明

1. 两大派生宏

  • #[derive(Serialize)]:Rust类型 → JSON字符串
  • #[derive(Deserialize)]:JSON字符串 → Rust类型

2. serde 常用字段标签

  1. #[serde(rename = "xxx")]
    自定义JSON内字段名称,解决下划线/驼峰命名差异
  2. #[serde(skip_serializing)]
    序列化时跳过该字段(密码、敏感数据不输出)
  3. #[serde(default)]
    JSON缺失此字段时,使用类型默认值(空字符串、0、false)
  4. #[serde(skip)]
    序列化+反序列化都忽略此字段
  5. #[serde(rename_all = "camelCase")]
    加在结构体上,批量把所有字段转为驼峰命名

3. serde_json 核心函数

  1. serde_json::to_string(&T)
    紧凑无换行JSON字符串
  2. serde_json::to_string_pretty(&T)
    带缩进、换行,人类可读格式化JSON
  3. serde_json::from_str::<T>(&str)
    JSON文本解析为指定Rust结构体
  4. json!({...})
    快速创建动态 serde_json::Value 对象,无需定义结构体
  5. serde_json::Value 动态类型六种分支
    • Value::Object 对象map
    • Value::Array 数组
    • Value::Number 数字
    • Value::String 字符串
    • Value::Bool 布尔
    • Value::Null 空值

六、典型业务拓展示例

示例1:Web统一返回格式(接口标准响应体)

#[derive(Serialize, Deserialize, Debug)]
pub struct ApiResp<T> {
    pub code: i32,
    pub msg: String,
    pub data: Option<T>,
}

// 成功返回泛型数据
fn success<T: Serialize>(data: T) -> ApiResp<T> {
    ApiResp {
        code: 200,
        msg: "ok".to_string(),
        data: Some(data),
    }
}

示例2:读取本地JSON配置文件

use std::fs::read_to_string;
fn load_config() -> User {
    let text = read_to_string("./config.json").unwrap();
    from_str(&text).unwrap()
}

七、优势说明

  1. 编译期生成序列化代码,无运行时反射,速度远超其他动态序列化库
  2. 标签系统灵活控制字段映射、过滤、默认值,适配前后端命名差异
  3. serde_json::Value 兼容未知结构第三方JSON,不用提前定义结构体
  4. 生态全覆盖:Axum、Tokio、sqlx、chrono、tracing 全部原生支持serde
  5. 支持泛型、嵌套、数组、枚举、日期等复杂业务类型无缝转换

更多推荐