Rust解析JSON,结构体序列化和反序列化

JSON一种常用的由键值对组成的数据对象;本文将通过多个例子讲解在Rust中如何解析JSON内容,以及如何将结构体转换成JSON字符串。

在Rust中解析JSON文本通常需要使用一个JSON库。Rust标准库中有一个名为serde的库,它提供了序列化和反序列化结构体和其他数据类型的功能,包括JSON。

添加依赖

要使用serde库解析JSON文本,你需要添加serdeserde_json依赖到你的项目中;

Cargo.toml文件中添加以下行:

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

解析JSON

对未类型化的JSON进行解析

任何有效的JSON数据都可以转换成serde_json::Value数据结构:

enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

以下函数可用于将JSON数据解析成serde_json::Value结构:

  • serde_json::from_str,用于解析JSON字符串;
  • serde_json::from_slice,用于对字节切片&[u8]进行解析;
  • serde_json::from_reader,从支持io::Read特性的对象中读取数据并解析,比如一个文件或TCP流;

一个使用serde_json::from_str的例子:

fn main() {

    // 一个&str类型的JSON数据
    let data = r#"
        {
            "name": "James Bond",
            "age": 33,
            "pet_phrase": [
                "Bond, James Bond.",
                "Shaken, not stirred."
            ]
        }"#;

    // 转换成serde_json::Value结构
    let v: serde_json::Value = serde_json::from_str(data).unwrap();

    // 通过方括号建立索引来访问部分数据
    println!("NAME: {}\nAGE: {}\n\t{}\n\t{}",
        v["name"],
        v["age"],
        v["pet_phrase"][0],
        v["pet_phrase"][1],
    );
}

程序运行结果

NAME: "James Bond"
AGE: 33
        "Bond, James Bond."
        "Shaken, not stirred."

将JSON解析到数据结构

serde提供了一种将JSON数据自动映射到Rust数据结构的方法;

修改前一个例子:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    pet_phrase: Vec<String>,
}

fn main() {

    // 一个&str类型的JSON数据
    let data = r#"
        {
            "name": "James Bond",
            "age": 33,
            "pet_phrase": [
                "Bond, James Bond.",
                "Shaken, not stirred."
            ]
        }"#;

    // 转换成 Person 结构
    let p: Person = serde_json::from_str(data).unwrap();

    // 通过方括号建立索引来访问部分数据
    println!("NAME: {}\nAGE: {}\n\t{}\n\t{}",
        p.name,
        p.age,
        p.pet_phrase[0],
        p.pet_phrase[1],
    );
}

该程序运行效果与上一个例子相同,但这一次我们将serde_json::from_str函数的返回值分配给了一个自定义的类型Person

JSON数据与结构体定义不符时将产生错误;

将数据结构转换成JSON字符串

以下是一些可以将数据结构转换成JSON数据的函数:

  • serde_json::to_string,将数据结构转换成JSON字符串;
  • serde_json::to_vec,将数据结构序列化为Vec<u8>
  • serde_json::to_writer,可以序列化到任何实现了io::Write特性的对象中,例如文件或 TCP 流;

使用serde_json::to_string的一个例子:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    pet_phrase: Vec<String>,
}

fn main() {

    let mut pp = Vec::new();
    pp.push("hello world".to_string());
    pp.push("perfcode.com".to_string());

    let p = Person {
        name: "ho".to_string(),
        age: 18,
        pet_phrase: pp,
    };

    // 序列化为JSON字符串
    let s = serde_json::to_string(&p).unwrap();

    println!("{}",s);
    
}

程序运行效果

{"name":"ho","age":18,"pet_phrase":["hello world","perfcode.com"]}

json!宏

serde提供了一个json!宏来非常自然的构建serde_json::Value对象:

use serde_json::json;

fn main() {

    let info = json!(
        {
            "name": "James Bond",
            "age": 33,
            "pet_phrase":[
                "Bond, James Bond.",
                "Shaken, not stirred."
                ]
        }
    );

    // 通过方括号建立索引来访问部分数据
    println!("NAME: {}\nAGE: {}\n\t{}\n\t{}",
        info["name"],
        info["age"],
        info["pet_phrase"][0],
        info["pet_phrase"][1],
    );

    //序列化
    println!("{}",info.to_string());

}

程序运行效果

NAME: "James Bond"
AGE: 33
        "Bond, James Bond."
        "Shaken, not stirred."
{"age":33,"name":"James Bond","pet_phrase":["Bond, James Bond.","Shaken, not stirred."]}

Value::to_string方法可以将serde_json::Value对象转换成 JSON 字符串;

原创内容,如需转载,请注明出处;

本文地址: https://www.perfcode.com/rust-serde/serde-json.html

分类: 计算机技术
推荐阅读:
Rust 宏编程 Rust 的宏编程是一种强大的元编程技术,允许您在编译时生成代码,创建自定义语法,以及进行各种代码转换。在 Rust 中,标准宏是内置于 Rust 标准库中的宏。这些宏是 Rust 语言提供的一部分,可直接在任何 Rust 代码中使用,无需额外的导入或引入其他依赖。
Golang中 :=的详细用法 在Go语言中:=运算符被用来声明变量以及给变量赋值,它可以自动推断变量类型;
Python使用集合实现内容去重 有这么一个场景,某个文件用于记录人名(也可以是URL或者其他的),编辑发现,出现了重复的内容。那么我们如何使用Python来进行去重呢?
提示Permission denied的解决方法 通常,提示Permission denied表示你的某个操作权限不够;在Linux系统中,权限分为读权限、写权限和可执行权限,当你所在的用户组没有相关权限时,则会提示Permission denied;
使用requests请求后的响应内容 使用Requests进行get请求或post请求后,requests会返回一个Response对象;
Rust语言中获取数组的大小 Rust语言中,数组提供len()方法可获取数组中的元素数量,即数组的大小;