跳过正文

serde_json

··1692 字
Rust Rust-Crate
rust crate - 这篇文章属于一个选集。
§ 17: 本文

serde_json 定义了 serde_json::Value 类型, 作为反序列化生成 通用类型, 可以对它使用 map index 操作来获得成员(类型是 &Value):

  • 使用 &str 字符串来获得 map 类型值, 可以使用整型 index 操作来获得数组成员;
  • 如果 index 的 map key 或 array index 不存在, 则返回 Value::Null;
  • 打印 Value 时, 返回 quota string。如果不想显示字符串 quota 双引号, 则可以调用 Value::as_str() 返回的字符串;
enum Value {
    Null,
    Bool(bool),
    Number(Number), // Number 为 serde_json 定义的通用数字类型
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

use serde_json::{Result, Value};

fn untyped_example() -> Result<()> {
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;
    // 返回的值为通用 serde_json::Value 类型, 如果失败则为 serde_json::Error 类型
    let v: Value = serde_json::from_str(data)?;
    println!("Please call {} at the number {}", v["name"], v["phones"][0]);
    Ok(())
}

serde_json::Value 类型提供了一些列方法,实现了 Index/IndexMut trait

pub fn get<I: Index>(&self, index: I) -> Option<&Value>
pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value>

pub fn is_object(&self) -> bool
pub fn as_object(&self) -> Option<&Map<String, Value>>
pub fn as_object_mut(&mut self) -> Option<&mut Map<String, Value>>

pub fn is_array(&self) -> bool
pub fn as_array(&self) -> Option<&Vec<Value>>
pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>>

pub fn is_string(&self) -> bool
pub fn as_str(&self) -> Option<&str>

pub fn is_number(&self) -> bool
pub fn as_number(&self) -> Option<&Number>
pub fn is_i64(&self) -> bool
pub fn is_u64(&self) -> bool
pub fn is_f64(&self) -> bool
pub fn as_i64(&self) -> Option<i64>
pub fn as_u64(&self) -> Option<u64>
pub fn as_f64(&self) -> Option<f64>

pub fn is_boolean(&self) -> bool
pub fn as_bool(&self) -> Option<bool>

pub fn is_null(&self) -> bool
pub fn as_null(&self) -> Option<()>

pub fn pointer(&self, pointer: &str) -> Option<&Value>
pub fn pointer_mut(&mut self, pointer: &str) -> Option<&mut Value>
pub fn take(&mut self) -> Value

impl<I> Index<I> for Value where    I: Index,
  fn index(&self, index: I) -> &Value
    type Output = Value

impl<I> IndexMut<I> for Value where    I: Index,
  fn index_mut(&mut self, index: I) -> &mut Value

// Index trait 定义, &str/String/usize 均实现了 Index trait
pub trait Index: Sealed { }
impl Index for str
impl Index for usize
impl Index for String
impl<T> Index for &T where T: ?Sized + Index,

可以使用 json!() 宏快速创建 Value 值, 宏的参数可以直接是 JSON 字面量形式,支持宏调用、函数或方法调用、变量:

let v = json!(null);
let v = json!(true);
let v = json!(12.5);
let v = json!("a string");
let v = json!(["an", "array"]);
let v = json!({ "an": "object" });

let body = &json!({
    "branch_name": branch,
    "commit_message": format!("apsarabot: update {name}"),
    "content": context,
    "file_path": name,
});

use serde_json::json;

fn main() {
    let john: serde_json::Value = json!({
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    });
    println!("first phone number: {}", john["phones"][0]);
    println!("{}", john.to_string());
}

let full_name = "John Doe";
let age_last_year = 42;
let john = json!({
    "name": full_name,
    "age": age_last_year + 1,
    "phones": [
        format!("+44 {}", random_phone())
    ]
});

对于实现了 Serialize/Deserialize trait 的自定义类型, 可以序列化和反序列化对应类型的值:

use serde::{Deserialize, Serialize};
use serde_json::Result;

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

fn typed_example() -> Result<()> {
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    let p: Person = serde_json::from_str(data)?;
    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

类型实现 Serialize trait 后, 可以使用 serde_json::to_string() 将对象转换为 JSON string :

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Address {
    street: String,
    city: String,
}

fn print_an_address() -> Result<()> {
    let address = Address {
        street: "10 Downing Street".to_owned(),
        city: "London".to_owned(),
    };

    let j = serde_json::to_string(&address)?;
    println!("{}", j);

    Ok(())
}

serde_json 提供了 ErrorResult 类型, 用于在 Serialize 或 Deserialize 出错时返回:

use serde_json::Value;
use std::io::{self, ErrorKind, Read};
use std::process;

struct ReaderThatWillTimeOut<'a>(&'a [u8]);

impl<'a> Read for ReaderThatWillTimeOut<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if self.0.is_empty() {
            Err(io::Error::new(ErrorKind::TimedOut, "timed out"))
        } else {
            self.0.read(buf)
        }
    }
}

fn main() {
    let reader = ReaderThatWillTimeOut(br#" {"k": "#);
    let _: Value = match serde_json::from_reader(reader) {
        Ok(value) => value,
        Err(error) => {
            if error.io_error_kind() == Some(ErrorKind::TimedOut) {
                // Maybe this application needs to retry certain kinds of errors.
            } else {
                eprintln!("error: {}", error);
                process::exit(1);
            }
        }
    };
}

serde_json module 提供的反序列化函数(均返回一个 T 类型对象):

// 下面返回的 Result 是 serde_json::Result, 它的 Err 为 serde_json::Error 类型

// 从实现 std::io::Read trait 的 reader 读取
pub fn from_reader<R, T>(rdr: R) -> Result<T> where R: Read, T: DeserializeOwned

// 从 &[u8] 读取
pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<T> where T: Deserialize<'a>

// 从 &str 读取
pub fn from_str<'a, T>(s: &'a str) -> Result<T> where T: Deserialize<'a>

// 从 serde_json::Value 读取
pub fn from_value<T>(value: Value) -> Result<T, Error> where T: DeserializeOwned

// 示例
use serde::Deserialize;
use std::error::Error;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;

#[derive(Deserialize, Debug)]
struct User {
    fingerprint: String,
    location: String,
}

fn read_user_from_file<P: AsRef<Path>>(path: P) -> Result<User, Box<dyn Error>> {
    let file = File::open(path)?;
    let reader = BufReader::new(file);
    let u = serde_json::from_reader(reader)?;
    Ok(u)
}

fn main() {
    let u = read_user_from_file("test.json").unwrap();
    println!("{:#?}", u);
}

use serde::Deserialize;
use serde_json::json;

#[derive(Deserialize, Debug)]
struct User {
    fingerprint: String,
    location: String,
}

fn main() {
    let j = json!({
        "fingerprint": "0xF9BA143B95FF6D82",
        "location": "Menlo Park, CA"
    });

    let u: User = serde_json::from_value(j).unwrap();
    println!("{:#?}", u);
}

从 Deserializer 创建的 StreamDeserializer,可以实现 流式反序列化

impl<'de, R, T> StreamDeserializer<'de, R, T> where R: Read<'de>, T: Deserialize<'de>,

// 可以从各种 serde_json::Read 来流式解码数据,例如:
// Deserializer::from_str(…).into_iter()
// Deserializer::from_slice(…).into_iter()
// Deserializer::from_reader(…).into_iter()
pub fn new(read: R) -> Self

pub fn byte_offset(&self) -> usize
// Returns the number of bytes so far deserialized into a successful T.

// StreamDeserializer 实现了 Iterator,每次迭代返回 T 对象
impl<'de, R, T> Iterator for StreamDeserializer<'de, R, T> where R: Read<'de>, T: Deserialize<'de>,
  type Item = Result<T, Error>

Deserializer 的 into_iter::<T>() 方法创建一个 StreamDeserializer;

  • 待解码的数据可以是任何 JSON Value 序列(而不仅限于一种值类型序列,序列值之间需要连续,不能有额外分割字符);
  • 每一次迭代,可以使用 stream.byte_offset() 来获得 bufer 中偏移量;
// 例子
let data = b"[0] [1] [";

let de = serde_json::Deserializer::from_slice(data);
let mut stream = de.into_iter::<Vec<i32>>();
assert_eq!(0, stream.byte_offset());

println!("{:?}", stream.next()); // [0]
assert_eq!(3, stream.byte_offset());

println!("{:?}", stream.next()); // [1]
assert_eq!(7, stream.byte_offset());

println!("{:?}", stream.next()); // error
assert_eq!(8, stream.byte_offset());

// If err.is_eof(), can join the remaining data to new data and continue.
let remaining = &data[stream.byte_offset()..];


// 另一个例子
use serde_json::{Deserializer, Value};

fn main() {
    let data = "{\"k\": 3}1\"cool\"\"stuff\" 3{}  [0, 1, 2]";

    let stream = Deserializer::from_str(data).into_iter::<Value>();

    for value in stream {
        println!("{}", value.unwrap());
    }
}

serde_json module 提供的序列化函数:

// 下面返回的 Result 是 serde_json::Result, 它的 Err 为 serde_json::Error 类型
pub fn to_value<T>(value: T) -> Result<Value, Error> where T: Serialize

// 序列化为 String
pub fn to_string<T>(value: &T) -> Result<String> where T: ?Sized + Serialize
pub fn to_string_pretty<T>(value: &T) -> Result<String> where T: ?Sized + Serialize

// 序列化为 Vec<u8>
pub fn to_vec<T>(value: &T) -> Result<Vec<u8>> where T: ?Sized + Serialize
pub fn to_vec_pretty<T>(value: &T) -> Result<Vec<u8>> where T: ?Sized + Serialize

// 序列化为 UTF-8 字节流, 然后写入 writer
pub fn to_writer<W, T>(writer: W, value: &T) -> Result<()> where W: Write, T: ?Sized + Serialize
pub fn to_writer_pretty<W, T>(writer: W, value: &T) -> Result<()> where W: Write, T: ?Sized + Serialize

// 示例
use serde::Serialize;
use serde_json::json;
use std::error::Error;

#[derive(Serialize)]
struct User {
    fingerprint: String,
    location: String,
}

fn compare_json_values() -> Result<(), Box<dyn Error>> {
    let u = User {
        fingerprint: "0xF9BA143B95FF6D82".to_owned(),
        location: "Menlo Park, CA".to_owned(),
    };
    let expected: serde_json::Value = json!({
        "fingerprint": "0xF9BA143B95FF6D82",
        "location": "Menlo Park, CA",
    });

    let v = serde_json::to_value(u).unwrap();
    assert_eq!(v, expected);
    Ok(())
}
rust crate - 这篇文章属于一个选集。
§ 17: 本文

相关文章

anyhow
··1874 字
Rust Rust-Crate
anyhow crate 提供了自定义 Error 类型和 Result 类型,Error 类型自带 backtrace 和 context,支持用户友好的格式化信息输出。
bytes
··2922 字
Rust Rust-Crate
bytes 提供了高效的 zero-copy 连续内存区域的共享和读写能力。
chrono
··4023 字
Rust Rust-Crate
chrono 提供了丰富的 Date/Time 类型和相关操作。
hyper
··861 字
Rust Rust-Crate
hyper 是高性能的异步 HTTP 1/2 底层库。