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

分类: 计算机技术
推荐阅读:
Python ord()函数 ord() 函数是 Python 内置函数之一,用于返回表示单个字符的 Unicode 码。它接受一个参数,即要获取 Unicode 码的字符。
Python @classmethod装饰器 在 Python 中,@classmethod 是一个装饰器,用于将一个普通方法转换为类方法。装饰器是一种语法糖,它可以修改已有函数的行为而不修改其定义。@classmethod 装饰器通常用于在类中定义类方法。
解决Golang中cannot refer to unexported name xxxx这类错误 在Golang中,碰到cannot refer to unexported name xxxx,这类错误,通常是你调用了一个包内不存在的函数导致的;
使用requests请求后的响应内容 使用Requests进行get请求或post请求后,requests会返回一个Response对象;
Python调用谷歌翻译API实现文本翻译 使用Python向谷歌翻译URL进行GET请求,得到网页内容后使用正则表达式进行解析,获得翻译结果;
Python breakpoint()函数 breakpoint()是 Python 3.7 中新增的一个调试工具,它是一个内置函数,可以在程序执行过程中插入一个断点,让程序停在该处等待调试器的进一步命令。