Сериализация и десериализация в Rust

Rust

Сериализация: процесс преобразования структуры данных или объекта в двоичную последовательность.

десериализовать: процесс преобразования двоичной последовательности, сгенерированной во время сериализации, в структуру данных или объект.

Serde — это общая структура для сериализации и десериализации структур данных Rust.

Черты Серде

Серде определяет 4 черты:

  • Deserialize A data structure that can be deserialized from any data format supported by Serde.
  • Deserializer A data format that can deserialize any data structure supported by Serde.
  • Serialize A data structure that can be serialized into any data format supported by Serde.
  • Serializer A data format that can serialize any data structure supported by Serde.

Serializeа такжеDeserialize

Serializeа такжеDeserializeОпределение:

pub trait Serialize {
    pub fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer;
}
pub trait Deserialize<'de>: Sized {
    pub fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>;
}

Чтобы тип данных поддерживал сериализацию и десериализацию, тип должен реализоватьSerializeа такжеDeserializeчерта. Serde предоставляет примитивы Rust и стандартные типы библиотек.Serializeа такжеDeserializeвыполнить.

Для пользовательских типов мы можем реализовать это самиSerializeа такжеDeserializeчерта. Кроме того, Serde предоставляет макросserde_deriveавтоматически генерировать для типов структур и типов перечисленияSerializeа такжеDeserializeвыполнить. Эта функция требует, чтобы версия компилятора Rust была1.31и выше, и вCargo.tomlПри настройке зависимостей Serde в файле необходимо использоватьfeaturesУкажите это свойство. Например:

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

Затем его можно импортировать и использовать в коде, например:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

Serializerа такжеDeserializer

Serializerа такжеDeserializerРеализации предоставляются сторонними крейтами, такими как:serde_json, serde_yamlа такжеbincode.

Частичный формат данных для реализации сообщества:

  • JSON, the ubiquitous JavaScript Object Notation used - by many HTTP APIs.
  • Bincode, a compact binary format used for IPC within - the Servo rendering engine.
  • CBOR, a Concise Binary Object Representation designed - for small message size without the need for version - negotiation.
  • YAML, a self-proclaimed human-friendly configuration - language that ain't markup language.
  • MessagePack, an efficient binary format that resembles - a compact JSON.
  • TOML, a minimal configuration format used by Cargo.
  • Pickle, a format common in the Python world.
  • RON, a Rusty Object Notation.
  • BSON, the data storage and network transfer format - used by MongoDB.
  • Avro, a binary format used within Apache Hadoop, with - support for schema definition.
  • JSON5, A superset of JSON including some productions - from ES5.
  • Postcard, a no_std and embedded-systems friendly - compact binary format.
  • URL query strings, in the x-www-form-urlencoded format.
  • Envy, a way to deserialize environment variables into - Rust structs. (deserialization only)
  • Envy Store, a way to deserialize AWS Parameter Store - parameters into Rust structs. (deserialization only)
  • S-expressions, the textual representation of code and - data used by the Lisp language family.
  • D-Bus's binary wire format.
  • FlexBuffers, the schemaless cousin of Google's - FlatBuffers zero-copy serialization format.
  • DynamoDB Items, the format used by rusoto_dynamodb to - transfer data to and from DynamoDB.

Serde JSON

существуетCargo.tomlДобавьте зависимости в файл:

[dependencies]
serde_json = "1.0"

Сериализация

serde_json Crate предоставляетserde_json::to_string,serde_json::to_vecа такжеserde_json::to_writerТри функции для преобразования типов данных Rust в JSONString,Vec<u8>а такжеio::Write(например, файл или поток TCP).

Пример:

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

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

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

    // Serialize it to a JSON string.
    let j = serde_json::to_string(&address)?;

    // Print, write to a file, or send to an HTTP server.
    println!("{}", j);

    Ok(())
}

десериализовать

serde_json Crate предоставляетserde_json::from_str,serde_json::from_sliceа такжеserde_json::from_readerТри функции нарезают строки, байты (&[u8]) и ввода-вывода (файл или поток TCP) в соответствующий тип данных Rust.

Пример:

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

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

fn typed_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into a Person object. This is exactly the
    // same function as the one that produced serde_json::Value above, but
    // now we are asking it for a Person as output.
    let p: Person = serde_json::from_str(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

Если данные формата JSON не имеют соответствующего типа данных Rust, их можно проанализировать какserde_json::ValueТипы.这是 serde_json Crate 提供的一个递归的枚举类型,它可以表示任何有效的 JSON 数据,其定义如下:

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

Разобрать данные формата JSON какserde_json::Valueтип, также используется:serde_json::from_str,serde_json::from_sliceа такжеserde_json::from_readerтри функции. Возвращаемое значение этих трех функций является универсальным, а тип возвращаемого значения определяется типом, присвоенным переменной.

Пример:

use serde_json::{Result, Value};

fn untyped_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into serde_json::Value.
    let v: Value = serde_json::from_str(data)?;
    // let v = serde_json::from_str::<Value>(data)?; // 或者可以这样写

    // Access parts of the data by indexing with square brackets.
    println!("Please call {} at the number {}", v["name"], v["phones"][0]);

    Ok(())
}

RON

существуетCargo.tomlДобавьте зависимости в файл:

[dependencies]
ron = "0.6.4"

RON (Rusty Object Notation) — это формат сериализации, аналогичный синтаксису Rust, который поддерживает всеМодель данных Серде.

Пример РОН:

Scene( // class name is optional
    materials: { // this is a map
        "metal": (
            reflectivity: 1.0,
        ),
        "plastic": (
            reflectivity: 0.5,
        ),
    },
    entities: [ // this is an array
        (
            name: "hero",
            material: "metal",
        ),
        (
            name: "monster",
            material: "plastic",
        ),
    ],
)

Особенности формата РОН:

  • использовать(..)Для представления структуры используйте{..}Чтобы представить карту, используйте[..]представляет собой массив. При работе с JSON нет различий между структурами и картами.
  • Комментарии можно добавлять, но не в формате JSON.
  • Как и в синтаксисе Rust, запятые добавляются к последнему элементу.

ron::value::Value

Подобно ящику serde_json, ящик ron также использует типы рекурсивного перечисления для представления данных формата RON. Этот тип перечисления:ron::value::Value, который определяется следующим образом:

pub enum Value {
    Bool(bool),
    Char(char),
    Map(Map),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

Сериализация и десериализация

Функции сериализации, предоставленные Роном Крейтом:

  • ron::ser::to_string: Serializes value and returns it as string.
  • ron::ser::to_string_pretty: Serializes value in the recommended RON layout in a pretty way.
  • ron::ser::to_writer: Serializes value into writer.
  • ron::ser::to_writer_pretty: Serializes value into writer in a pretty way.

Функции десериализации, предоставленные Роном Крейтом:

  • ron::de::from_bytes: Building a deserializer and deserializing a value of type T from bytes.
  • ron::de::from_str: Reading data from a reader and feeding into a deserializer.
  • ron::de::from_reader: Building a deserializer and deserializing a value of type T from a string.

Пример:

use serde::{Deserialize, Serialize};
use std::fs::File;

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point1 = Point { x: 1, y: 2 };
    // Serializes point1 into a buffer
    let mut buf = Vec::<u8>::new();
    ron::ser::to_writer(&mut buf, &point1).unwrap();
    println!("buf = {:?}", buf);

    let point2: Point = ron::de::from_bytes(&buf).unwrap();
    println!("point2: {:?}", point2);

    let point3 = Point { x: 3, y: 4 };
    // Serializes point3 and returns it as string
    let point_str = ron::to_string(&point3).unwrap();
    println!("point_str: {:?}", point_str);

    let point4: Point = ron::from_str(&point_str).unwrap();
    println!("point4: {:?}", point4);

    let point5 = Point { x: 5, y: 6 };
    let file = File::create("foo.txt").unwrap();
    // Serializes point5 into foo.txt
    ron::ser::to_writer(file, &point5).unwrap();

    let file = File::open("foo.txt").unwrap();
    let point6: Point = ron::de::from_reader(file).unwrap();
    println!("point6: {:?}", point6);
}

BSON

существуетCargo.tomlДобавьте зависимости в файл:

[dependencies]
bson = "1.1.0"

BSON (Binary JSON) — это JSON-подобный формат (документ) в двоичной форме.

пример BSON:

// JSON equivalent
{"hello": "world"}

// BSON encoding
\x16\x00\x00\x00                   // total document size
\x02                               // 0x02 = type String
hello\x00                          // field name
\x06\x00\x00\x00world\x00          // field value
\x00                               // 0x00 = type EOO ('end of object')

Значение BSON

Многие различные типы данных могут быть представлены как значения BSON,BsonТипы перечисления определяют все типы, которые могут быть представлены как значения BSON.

Пример: создать экземпляр Bson

// 直接创建 Bson 实例
let string = Bson::String("hello world".to_string());
let int = Bson::Int32(5);
let array = Bson::Array(vec![Bson::Int32(5), Bson::Boolean(false)]);

// 使用 into() 创建 Bson 实例
let string: Bson = "hello world".into();
let int: Bson = 5i32.into();

// 使用 `bson!` 宏创建 Bson 实例
let string = bson!("hello world");
let int = bson!(5);
let array = bson!([5, false]);

BSON documents

Документ в Bson состоит из упорядоченного набора пар ключ-значение, подобно Object в JSON. Кроме того, также включен размер пространства, занимаемого значением Bson.

Пример 1: создать экземпляр документа

let mut bytes = hex::decode("0C0000001069000100000000").unwrap();
// 直接创建
let doc = Document::from_reader(&mut bytes.as_slice()).unwrap(); // { "i": 1 }

// 通过 doc! 创建
let doc = doc! {
   "hello": "world",
   "int": 5,
   "subdoc": { "cat": true },
};

Пример 2: доступ к членам документа

let doc = doc! {
   "string": "string",
   "bool": true,
   "i32": 5,
   "doc": { "x": true },
};

// attempt get values as untyped Bson
let none = doc.get("asdfadsf"); // None
let value = doc.get("string"); // Some(&Bson::String("string"))

// attempt to get values with explicit typing
let string = doc.get_str("string"); // Ok("string")
let subdoc = doc.get_document("doc"); // Some(Document({ "x": true }))
let error = doc.get_i64("i32"); // Err(...)

Сериализация и десериализация

Функции сериализации, предоставляемые bson Crate:

  • bson::to_bson: Encode a T Serializable into a BSON Value.
  • bson::to_document: Encode a T Serializable into a BSON Document.

Функции десериализации, предоставляемые bson Crate:

  • bson::from_bson: Decode a BSON Value into a T Deserializable.
  • bson::from_document: Decode a BSON Document into a T Deserializable.

Пример:

use bson::*;
use serde::{Deserialize, Serialize};

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

fn main() {
    // Some BSON input data as a `Bson`.
    let bson_data: Bson = bson!({
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    });

    // Deserialize the Person struct from the BSON data.
    let person: Person = bson::from_bson(bson_data).unwrap();

    // Do things just like with any other Rust data structure.
    println!("Redacting {}'s record.", person.name);

    // Get a serialized version of the input data as a `Bson`.
    let redacted_bson = bson::to_bson(&person).unwrap();
    println!("{}", redacted_bson);
}

Релевантная информация

Serde

JSON

RON

BSON