Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Тема
Описание
Доп.

📌 Новый раздел

  • 👾 Best practice
  • Варианты применения
  • 👾 Теперь нет смысла собирать примеры методов, с LLMs можно актуальные реальные примеры применения рассматривать До LLM был смысл в сборе примеров так как документация не имела нужных примеров ведь она имеет свою структуру и сбор подходов и объяснений на сайтах типа medium... НО теперь LLM может тебе объяснит все по полочкам с примерами. Теперь нужно с LLM пройтись по темам и собрать общее понимание подходов и библиотек с перечнем методов чего они могут. Например, тема асинхронного программирования довольно запутана, ее можно расписать по полочкам и т.д. все темы.

Bincode (бинарная сериализация)

#![allow(unused)]
fn main() {
use bincode;

let value: u32 = 42;
let encoded: Vec<u8> = bincode::serialize(&value).unwrap();
let decoded: u32 = bincode::deserialize(&encoded).unwrap();
}

Дополнительно

рассмотреть возможность serde установки дополнительных экосистемных ящиков, которые расширяют возможности оборудования:

crate erased-serde, предоставляющий версии со стертыми типами serde и Serialize типажи Serializer, Deserializer которые можно использовать в качестве объектов типажей.

crate serde_state, расширяя нормали Deserialize и Serialize черты, чтобы позволить передавать состояние каждому значению, которое сериализуется или десериализуется.

crate serde_repr, производя serde'ы Serialize и Deserialize признаки таким образом, чтобы делегировать их базовому представлению C-подобного перечисления.

crate serde_with, предоставляющий специальные помощники де/сериализации для использования в сочетании с serde-annotation with и улучшенной -annotation serde_as.

crate serde_valid, позволяющий осуществлять проверку на основе схемы JSON .

Serde Структура данных, которая знает, как сериализовать и десериализовать себя, — это структура, которая реализует черты Serde Serialize и Deserialize

В то время как многие другие языки полагаются на рефлексию времени выполнения для сериализации данных, Serde вместо этого построен на мощной системе черт Rust. Структура данных, которая знает, как сериализовать и десериализовать себя, — это та, которая реализует черты Serde Serialize и Deserialize (или использует атрибут derive Serde для автоматической генерации реализаций во время компиляции). Это позволяет избежать любых накладных расходов на рефлексию или информацию о типе времени выполнения.

Форматы:

  • JSON использовать crate serde_json
  • TOML использовать crate toml
  • YAML использовать crate serde_yaml
  • URL использовать crate serde_qs
  • CSV использовать crate csv

Online инструмент transform трансформирует JSON в структуры Rust

Из коробки Serde способен сериализовать и десериализовать распространенные типы данных Rust в любом из вышеперечисленных форматов. Например: String, поддерживаются все форматы &str, usize, Vec<T>, HashMap<K,V>


use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use serde_json;
fn main() {
    let my_string = "Hello, World!".to_string();
    let my_str: &str = "Hello, World!";
    let my_number: usize = 42;
    let my_vec = vec![1, 2, 3];
    let mut my_map = HashMap::new();
    {
        my_map.insert("key1", "value1");
        my_map.insert("key2", "value2");
    }

    let serialized:String = serde_json::to_string(&my_string).unwrap();
    assert_eq!("\"Hello, World!\"", serialized); // "Hello, World!"
    let deserialize: String  = serde_json::from_str(&serialized).unwrap();
    assert_eq!("Hello, World!", deserialize);
 
    let serialized:String = serde_json::to_string(&my_str).unwrap();
    assert_eq!("\"Hello, World!\"", serialized); // "Hello, World!"
    let deserialize: &str  = serde_json::from_str(&serialized).unwrap();
    assert_eq!("Hello, World!", deserialize);
    
    let serialized:String = serde_json::to_string(&my_number).unwrap();
    assert_eq!("42", serialized); // "42"
    let deserialize: usize  = serde_json::from_str(&serialized).unwrap();
    assert_eq!(42_usize, deserialize);
    
    let serialized:String = serde_json::to_string(&my_vec).unwrap();
    assert_eq!("[1,2,3]", serialized); // [1,2,3]
    let deserialize: Vec  = serde_json::from_str(&serialized).unwrap();
    assert_eq!([1,2,3].to_vec(), deserialize);
    
    let serialized:String = serde_json::to_string(&my_map).unwrap();
    // ключи могут иметь другой порядок!
    assert_eq!("{\"key1\":\"value1\",\"key2\":\"value2\"}", serialized); // {"key1":"value1","key2":"value2"}
    let deserialize: HashMap<&str,&str> = serde_json::from_str(&serialized).unwrap();
    assert_eq!(my_map, deserialize);
}
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

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

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

fn main() -> Result<()> {
    let person = Person { name: "John Doe".to_string(), age: 2_u8, phones:vec![]};
    let person_str = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    let person: Person  = serde_json::from_str(&person_str).unwrap();// Deserialize
    println!("deserialized = {:?}", person);// Person { name: "John Doe", age: 43, phones: ["+44 1234567", "+44 2345678"] }
    let person_str:String = serde_json::to_string(&person).unwrap();// Serialize

// From To File
    println!("serialized = {}", &person_str);// {"name":"John Doe","age":43,"phones":["+44 1234567","+44 2345678"]}
    std::fs::write("person.txt", person_str);
    let person_str:String = std::fs::read_to_string("person.txt").unwrap(); 

    Ok(())
}

serde_json::json!

Макрос json! преобразует Rust-значения в экземпляры serde_json::Value. Например:


fn main(){
    "text" → Value::String("text".to_string())
    123 → Value::Number(123)
    [1, 2, 3] → Value::Array(vec![Value::Number(1), Value::Number(2), Value::Number(3)])
    { "key": "value" } → Value::Object(Map::from_iter(vec![("key".to_string(), Value::String("value".to_string()))]))
}


use serde_json::json;
fn main(){
    let object:serde_json::Value = json!({
        "code": 200,
        "success": true,
        "payload": {
            "features": [
                "serde",
                "json"
            ],
            "homepage": null
        }
    });
}

Без макроса json!, создание такой структуры было бы менее удобным:


use serde_json::{Map, Value};
fn main() {
    let mut address = Map::new();
    address.insert("city".to_string(), Value::String("Wonderland".to_string()));
    address.insert("postcode".to_string(), Value::Number(12345.into()));

    let mut object = Map::new();
    object.insert("name".to_string(), Value::String("Alice".to_string()));
    object.insert("age".to_string(), Value::Number(30.into()));
    object.insert("is_admin".to_string(), Value::Bool(true));
    object.insert("hobbies".to_string(), Value::Array(vec![
        Value::String("reading".to_string()),
        Value::String("cycling".to_string())
    ]));
    object.insert("address".to_string(), Value::Object(address));

    println!("{}", Value::Object(object));
}

std::ffi::OsString этот тип представляет собой собственную строку платформы. В системах Unix это произвольные ненулевые байты, а в системах Windows это произвольные ненулевые 16-битные значения.

Если отобразить OsStringв модель данных Serde как строка Serde. К сожалению, сериализация будет ненадёжной, поскольку OsStringне гарантируется её представление в UTF-8, а десериализация будет ненадёжной, поскольку строкам Serde разрешено содержать 0 байтов.

Если отобразить OsString в модель данных Serde как массив байтов Serde. Это устраняет обе проблемы с использованием строки, но теперь, если мы сериализуем ее OsStringв Unix и десериализуем ее в Windows, мы получим неправильную строку из-за разногласия старших байт и сколько байт на символ взять для преобразования в символ

Вместо этого Serialize и Deserialize impls for OsString отображаются в модели данных Serde, обрабатывая их как перечисление OsString Serde:

  • Unix: OsString сериализуется как Vec<u8>, так как строки в Unix могут быть произвольными байтами, кроме нулевых.
  • Windows: OsString сериализуется как Vec<u16>, поскольку строки в Windows — это последовательности 16-битных значений.
  • Другие платформы: Если платформа имеет другое представление строк, оно будет закодировано подобным образом.

use serde::{Deserialize, Serialize};
use std::ffi::OsString;

#[derive(Serialize, Deserialize, Debug)]
struct MyStruct {
    value: OsString,
}
fn main() -> Result<(), Box> {
    // Создаем `OsString`
    let os_string = OsString::from("Привет, мир!");

    let my_struct = MyStruct { value: os_string };

    // Сериализация
    let serialized = serde_json::to_string(&my_struct)?;
    println!("Сериализовано: {}", serialized);

    // Десериализация
    let deserialized: MyStruct = serde_json::from_str(&serialized)?;
    println!("Десериализовано: {:?}", deserialized);
    Ok(())
}

Атрибуты

(используются если есть derive)

serde.rs/attributes

Существует три категории атрибутов:

  • Container attributes — применяются к объявлению структуры или enum
  • Variant attributes — применяются к варианту enum
  • Field attributes — применяются к одному полю в структуре или в варианте enum

Атрибуты контейнера

  • Сериализуйте и десериализуйте эту структуру или перечисление, используя заданное имя

    #[serde(rename(serialize = "ser_name", deserialize = "de_name"))]

  • Переименуйте все поля в соответствии с заданным регистром.

    #[serde(rename_all(serialize = "snake_case", deserialize = "UPPERCASE"))]

  • Для Serialize вывод имени структуры или enum

    #[serde(tag = "type")]

  • Предложение Where для реализаций Serialize и Deserialize. Это заменяет любые границы, выведенные Serde

    • #[serde(bound = "T: MyTrait")]
    • #[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
  • При десериализации все недостающие поля должны быть заполнены из реализации структуры Default. Разрешено только в структурах.

    #[serde(default)]

  • При десериализации все недостающие поля должны быть заполнены из заданной ф-ции. Разрешено только в структурах.

    #[serde(default = "path")]

  • Атрибут, указывающий, что представление типа совпадает с его единственным полем

    #[serde(transparent)]

  • Десериализуйте этот тип, десериализовав его в FromType, а затем преобразовав. Этот тип должен реализовывать From<FromType>, а FromType должен реализовывать десериализацию

    • #[serde(from = "FromType")]
    • #[serde(try_from = "FromType")]
    • #[serde(into = "IntoType")]
  • Это используется для получения Serialize и Deserialize для remote types

    #[serde(remote = "...")]

  • Используйте представление перечисления без тегов для этого перечисления

    #[serde(untagged)]

Атрибуты поля

  • Сериализуйте и десериализуйте это поле, используя заданное

    • #[serde(rename = "name")]
    • #[serde(rename(serialize = "ser_name", deserialize = "de_name"))]
  • Десериализуйте это поле по заданному имени или по имени текущему имени поля

    #[serde(alias = "name")]

  • Если значение отсутствует при десериализации подставится Default

    • #[serde(default)]
    • #[serde(default = "path")]
  • Для разложения общих ключей в общую структуру

    #[serde(flatten)]

  • Пропустите это поле: не сериализуйте и не десериализуйте его. При десериализации Serde будет использовать Default::default()

    • #[serde(skip)]
    • #[serde(skip_serializing)]
    • #[serde(skip_deserializing)]
  • Пропустите сериализацию этого поля если условие не выполняется

    #[serde(skip_serializing_if = "path")]

  • Сериализуйте/Десериализуйте это поле, используя свои функции

    • #[serde(serialize_with = "path")]
    • #[serde(deserialize_with = "path")]
    • #[serde(with = "module")]
  • Заимствуйте данные

    • #[serde(borrow)]
    • #[serde(borrow = "'a + 'b + ...")]
  • Предложение Where для реализаций Serialize и Deserialize. Это заменяет любые границы, выведенные Serde

    • #[serde(bound(serialize = "T: MySerTrait"))]
    • #[serde(bound(deserialize = "T: MyDeTrait"))]
    • #[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
  • Это используется при получении Serialize для remote type, который имеет одно или несколько частных полей

    #[serde(getter = "...")]

Предложение Where для реализаций Serialize и Deserialize. Это заменяет любые границы, выведенные Serde

  • #[serde(bound = "T: MyTrait")]

  • #[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]

  • #[serde(bound(deserialize = "S: FromStr, S::Err: Display"))]

  • #[serde(bound(deserialize = "Ptr<'a, T>: Deserialize<'de>"))]


#[derive(Debug, serde::Deserialize)]
pub struct Config {
    pub name: &'static str,
}

#[derive(Debug, serde::Deserialize)]
#[serde(bound(deserialize = "'de: 'static"))] // без указания времени жизни не скомпилируется
struct SourceConfig {
    config: Config,
    id: u32,
}
 
fn main() -> serde_json::Result<()> {
    let j = r#"
    {
        "id": 123,
        "config": {
            "name": "John Smith"
        }
    }
        "#;
        
let sc: SourceConfig = serde_json::from_str(&j).unwrap();
dbg!(sc);
}

Однако вы, вероятно, не захотите десериализовать &'static str, так как для этого потребуется наличие &'static str для заимствования. Это ограничивает вас либо строковыми литералами, либо вам потребуется утечка памяти для получения &'static str. Вероятно, вам понадобится String или, если вы хотите поддерживать строковые литералы, Cow<'a, str>.

Другая проблема с &'a str заключается в том, что он не будет работать, если строка сериализована с помощью escape-последовательностей. Например, строка JSON, содержащая разрыв строки, будет иметь \n, который необходимо заменить во время десериализации, что приведет к сбою, если вы используете &'a str.

Атрибуты контейнера

handwritten-generic-type-bounds

Предложение Where для реализаций Serialize и Deserialize. Это заменяет любые границы, выведенные Serde

  • #[serde(bound = "T: MyTrait")]
  • #[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
  • #[serde(bound(deserialize = "S: FromStr, S::Err: Display"))]
  • #[serde(bound(deserialize = "Ptr<'a, T>: Deserialize<'de>"))]

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
use serde::de::{self, Deserialize, Deserializer};
use std::fmt::Display;
use std::str::FromStr;
#[derive(Deserialize, Debug)]
struct Outer {
// При получении Deserialize impl, Serde захочет создать связанный
// `T: Deserialize` в типе этого поля. Но мы собираемся использовать `FromStr` вместо `Deserialize`, используя
// `deserialize_from_str`, поэтому мы переопределяем автоматически созданный bound
// тем, который требуется для` deserialize_from_str`,
    #[serde(deserialize_with = "deserialize_from_str")]
    #[serde(bound(deserialize = "T: FromStr, T::Err: Display"))]
    s: T,
}
fn deserialize_from_str<'de, T, D>(deserializer: D) -> Result
    where
        T: FromStr,
        T::Err: Display,
        D: Deserializer<'de>,
{
    let s: String = Deserialize::deserialize(deserializer)?;
    T::from_str(&s).map_err(de::Error::custom)
}
fn main() {
    let j = r#"
        {
          "s": "1234567890"
        }
    "#;
    let result: Outer = serde_json::from_str(j).unwrap();
    // result = Outer { s: 1234567890 }
    println!("result = {:?}", result);
}


#[derive(Deserialize, Debug)]
struct  Outer {
    s:u64,
    ptr:Ptr
}
enum Ptr<'a, T: 'a + ?Sized> {
    Ref(&'a T),
    Owned(Box),
}

fn main() {
    let j = r#"
        {
          "s": "1234567890",
          "ptr": "owned"
        }
    "#;
    let result: Outer = serde_json::from_str(j).unwrap();
   // let result: Outer  = serde_json::from_str(j).unwrap();

    // result = Outer { s: 1234567890, ptr: Owned("owned") }
    println!("result = {:?}", result);
}
// panic "s": "1234567890" не может преобразоваться в s:u64
// И ptr это enum Ptr который надо создать из строки "owned"

Атрибуты контейнера

handwritten-generic-type-bounds

Предложение Where для реализаций Serialize и Deserialize. Это заменяет любые границы, выведенные Serde

  • #[serde(bound = "T: MyTrait")]
  • #[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
  • #[serde(bound(deserialize = "S: FromStr, S::Err: Display"))]
  • #[serde(bound(deserialize = "Ptr<'a, T>: Deserialize<'de>"))]

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
use serde::de::{self, Deserialize, Deserializer};
use std::fmt::Display;
use std::str::FromStr;
#[derive(Deserialize, Debug)]
struct Outer<'a,  T: 'a + ?Sized> {
// Здесь Serde хотел бы создать привязку `T: Deserialize`. Это более строгое условие
//, чем это необходимо. Фактически, функция `main` ниже
// использует T = str, которая не реализует Deserialize. Мы переопределяем
// автоматически сгенерированную привязку (bound) более свободно.
    #[serde(bound(deserialize = "Ptr<'a, T>: Deserialize<'de>"))]
    ptr: Ptr<'a, T>,

}
/// Указатель на `T`, который может или не может владеть данными. При десериализации мы
/// всегда хотим создавать собственные данные.
#[derive(Debug)]
enum Ptr<'a, T: 'a + ?Sized> {
    Ref(&'a T),
    Owned(Box),
}
impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for Ptr<'a, T>
 where Box: Deserialize<'de>,
{
    fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>,
    {
        Deserialize::deserialize(deserializer).map(Ptr::Owned)
    }
}
fn main() {
    let j = r#"
        {
          "ptr": "owned value"
        }
    "#;
    let result: Outer = serde_json::from_str(j).unwrap();
    println!("result = {:?}", result);  // result = Outer { ptr: Owned("owned value") }
}

Атрибуты контейнера

При десериализации все недостающие поля должны быть заполнены из заданной ф-ции. Разрешено только в структурах.

#[serde(default = "path")]


#[derive(Serialize,Deserialize, Debug)]
#[serde(default = "some_default")]
struct MyStruct{
    value:i32
}
fn some_default()->MyStruct{
    MyStruct{value:8}
}
fn main() -> serde_json::Result<()> {
   let st_string = r#"{}"#;
   let st: MyStruct = serde_json::from_str(&st_string)?;// Deserialize
   println!("deserialized = {:?}", st);// MyStruct { value: 8 }
}

Атрибуты контейнера

Атрибут, указывающий, что представление типа совпадает с его единственным полем

#[serde(transparent)]

use serde::{Serializer,Deserializer}; 
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
//#[derive(Debug)]
struct Transparent(String);

// или 

impl Serialize for Transparent {
    fn serialize<T>(&self, serializer: T) -> std::result::Result<T::Ok, T::Error>
        where T: Serializer
    {
        self.0.serialize(serializer)
    }
}
impl<'de> Deserialize<'de> for Transparent {
    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Deserialize::deserialize(deserializer).map(Transparent)
    }
}

Атрибуты контейнера

Десериализуйте этот тип, десериализовав его в FromType, а затем преобразовав. Этот тип должен реализовывать From<FromType>, а FromType должен реализовывать десериализацию

#[serde(from = "FromType")]

#[serde(try_from = "FromType")]

#[serde(into = "IntoType")]


#[derive(Serialize,Deserialize, Debug)]
struct Something(i32);
 
#[derive(Serialize,Deserialize, Debug)]
#[serde(from = "Something")]
struct Something2(i32);

impl std::convert::From for Something2 {
    fn from(item: Something) -> Self {
        Something2(item.0+5)
    }
}
fn main() -> serde_json::Result<()> {
   let s_string = r#"7"#;
   let s: Something2 = serde_json::from_str(&s_string)?;// Deserialize 
   println!("deserialized = {:?}", s); // Something2(12)
   let s_string = serde_json::to_string(&s).unwrap();// Serialize 
   assert_eq!("12", s_string);
}

Атрибуты контейнера

Это используется для получения Serialize и Deserialize для remote types

#[serde(remote = "...")]

Есть remote types bar::Bar у которого нет реализации Serialize/Deserialize тогда мы можем ее получить через подставной тип MockBar с помошью ссылки #[serde(remote = "Bar")]


pub use bar::Bar;
mod bar{
    #[derive(Debug)] 
    pub struct Bar {
        pub value:i32
    }   
} 

#[serde(remote = "Bar")]
#[derive(Serialize,Deserialize,Default,Debug)]
pub struct MockBar{
    value:i32
}

#[derive(Serialize,Deserialize,Debug)]
struct Process {
    #[serde(with = "MockBar")] // использовать Serialize/Deserialize от MockBar
    something: Bar,
}

fn main() -> serde_json::Result<()> {
// Получить Serialize/Deserialize для Bar
    let f_string = r#"{"value":4}"#;
    let mut de = serde_json::Deserializer::from_str(f_string);
    let bar:Bar = MockBar::deserialize(&mut de)?;
    println!("deserialized = {:?}",bar); // Bar { value: 4 }
//--------------------------------------------------------------------
// Теперь для вложенных данных Bar
    let p_string = r#"{"something":{"value":4}}"#;
    let p: Process = serde_json::from_str(&p_string)?;
    println!("deserialized = {:?}",p);// Process { something: Bar { value: 4 } }
     
    let p_string = serde_json::to_string(&p).unwrap();
    println!("serialized = {}", &p_string);// {"something":{"value":4}}
}

Атрибуты контейнера

Используйте представление перечисления без тегов для этого перечисления

#[serde(untagged)]


use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize,PartialEq, Debug)]
#[serde(untagged)] 
enum Message {
    Singl (User),
    Batch (Vec),
}

#[derive(Serialize, Deserialize,PartialEq,Debug)]
struct User{
    name:String
}

fn main() {
  let res = serde_json::from_str::( r#"[{"name": "jeka"}, {"name": "tolik"}]"#).unwrap();
  assert_eq!(Message::Batch(vec![User{name:"jeka".to_string()},User{name:"tolik".to_string()}]),res);
 
  let res = serde_json::from_str::( r#"{"name": "jeka"}"#).unwrap();
  assert_eq!(Message::Singl(User{name:"jeka".to_string()}),res);
}

Атрибуты поля

Заимствуйте данные

#[serde(borrow)]

#[serde(borrow = "'a + 'b + ...")]


#[derive(Debug,Serialize, Deserialize,Default)]
pub struct Config<'a> {
    pub name: std::borrow::Cow<'a,str>,
}

#[derive(Debug,Serialize, Deserialize)]
struct SourceConfig<'a>  {
    #[serde(borrow)]
    config: Config<'a>,
    id: u32,
}

fn main() -> serde_json::Result<()> {
    let j = r#"{"id": 123,"config": {"name": "John Smith" }}"#;
    let src: SourceConfig = serde_json::from_str(&j).unwrap();// Deserialize 
    let src_string = serde_json::to_string(&src).unwrap();// Serialize
    let src: SourceConfig = serde_json::from_str(&src_string)?;// Deserialize 

    let sc: Config = Config::default();
    let p_string = serde_json::to_string(&sc).unwrap();// Serialize
    let p: Config = serde_json::from_str(&p_string)?;// Deserialize       
}

Атрибуты поля

Сериализуйте и десериализуйте это поле, используя заданное

#[serde(rename = "name")]

#[serde(rename(serialize = "ser_name", deserialize = "de_name"))]

#[derive(Serialize,Deserialize)]
struct People{
    #[serde(rename = "something")]
    some_thing:i32
}

Атрибуты поля

Десериализуйте это поле по заданному имени или по имени текущему имени поля

#[serde(alias = "name")]


#[derive(Serialize,Deserialize)]
struct People{
    #[serde(alias = "Some_Thing", alias = "something")]
    some_thing:i32
}
fn main() -> serde_json::Result<()> {
    let p_string = r#"{"some_thing": 3}"#;
    let p_string = r#"{"something": 3}"#;
    let p_string = r#"{"Some_Thing": 3}"#;
    let p: People = serde_json::from_str(&p_string)?;// Deserialize
    println!("deserialized = {:?}", p);
}

Атрибуты поля

Если значение отсутствует при десериализации подставится Default

#[serde(default)]

#[serde(default = "path")]


#[derive(Serialize,Deserialize)]
struct People{
    #[serde(default)]
    some_thing:i32
}
fn main() -> serde_json::Result<()> {
    let p_string = r#"{}"#;
    let p: People = serde_json::from_str(&p_string)?;// Deserialize
   // People { some_thing: 0 }
}

Атрибуты поля

Для разложения общих ключей в общую структуру

#[serde(flatten)]


use std::collections::HashMap; 
#[derive(Serialize,Deserialize, Debug)]
struct People{
    id: String,

    #[serde(flatten)]
    extra: HashMap,
}

fn main() -> serde_json::Result<()> {
    let mut map:HashMap = HashMap::new();
    map.insert("mascot".to_owned(),"Ferris".into());

    let p = People{id:"123".into(),extra:map};
    let p_string = serde_json::to_string(&p).unwrap();// Serialize
    println!("serialized = {}", &p_string);// {"id":"123","mascot":"Ferris"}

    let p: People = serde_json::from_str(&p_string)?;// Deserialize
    println!("deserialized = {:?}", p);// People { id: "123", extra: {"mascot": String("Ferris")} }
}

Атрибуты поля

Пропустите это поле: не сериализуйте и не десериализуйте его. При десериализации Serde будет использовать Default::default()

#[serde(skip)]


#[derive(Default,Debug)]
struct Something(i32);
 
use std::collections::HashMap; 
#[derive(Serialize,Deserialize,Debug)]
struct People{
    id: i32,
    
    #[serde(skip)]
    something:Something 
}
fn main() -> serde_json::Result<()> {
    let person_str = r#"{"id":23}"#;
    let p: People = serde_json::from_str(&person_str)?;// Deserialize
    println!("deserialized = {:?}", p);// People { id: 23, something: Something(0) }
}

Атрибуты поля

Пропустите сериализацию этого поля если условие не выполняется

#[serde(skip_serializing_if = "path")]


#[derive(Serialize,Deserialize, Debug)]
struct People{
    id: i32,

    #[serde(skip_serializing_if = "Something::if_ser")]
    something:Something 
}

fn main() -> serde_json::Result<()> {
    let p = People{id:123,something:Something(255)};
    let p_string = serde_json::to_string(&p).unwrap();// Serialize
    println!("serialized = {}", &p_string);// {"id":123}

   // На Deserialize это не влияет
    let p_string = r#"{"id":23,"something":255}"#;
    let p: People = serde_json::from_str(&p_string)?;// Deserialize
    println!("deserialized = {:?}", p);// People { id: 23, something: Something(255) }
}

Сериализуйте/Десериализуйте это поле, используя свои функции

#[serde(serialize_with = "path")]

#[serde(deserialize_with = "path")]

#[serde(with = "module")]


use chrono::NaiveDate;
use serde;
use serde_derive::{Deserialize, Serialize};
use serde_json;

mod date_serde {
    use chrono::NaiveDate;
    use serde::{self, Deserialize, Deserializer, Serializer};

    pub fn serialize(date: &Option, s: T) -> Result where T: Serializer {
        if let Some(ref d) = *date {
            return s.serialize_str(&d.format("%Y-%m-%d").to_string());
        }
        s.serialize_none()
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de> {
        let s: Option = Option::deserialize(deserializer)?;
        if let Some(s) = s {
            return Ok(Some(
                NaiveDate::parse_from_str(&s, "%Y-%m-%d").map_err(serde::de::Error::custom)?,
            ));
        }
        Ok(None)
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct Test {
    pub i: u64,
    #[serde(default)]
    #[serde(with = "date_serde")]
    pub date: Option,
}

fn main() -> Result<(), serde_json::Error> {
    let mut test: Test = serde_json::from_str(r#"{"i": 3, "date": "2015-02-03"}"#)?;
    assert_eq!(test.i, 3);
    assert_eq!(test.date, Some(NaiveDate::from_ymd(2015, 02, 03)));
    test = serde_json::from_str(r#"{"i": 5}"#)?;
    assert_eq!(test.i, 5);
    assert_eq!(test.date, None);
    
    Ok(())
}

Атрибуты поля

Это используется при получении Serialize для remote type, который имеет одно или несколько частных полей

#[serde(getter = "...")]


use serde::{Deserialize, Serialize};
trait Fake{
    fn get_value(&self) -> Vec;
}
impl Fake for String{
    fn get_value(&self) -> Vec{
        vec![0u8;1]
        //unimplemented!()
    }
}

#[serde(remote = "std::string::String")]
#[derive(Serialize,Deserialize,Debug)]
pub struct MockString {
    #[serde(getter = "String::get_value")]
    vec: Vec
}
impl std::convert::From for String {
    fn from(item: MockString) -> String {
        String::from_utf8(item.vec).unwrap_or_default()  
    }
}
fn main() -> serde_json::Result<()>{
    let mock_string:&str = r#"{"vec":[104, 101, 108, 108, 111]}"#;
    let mut de = serde_json::Deserializer::from_str(mock_string);
    let string:String = MockString::deserialize(&mut de)?;
    println!("deserialized = {:?}",string);// hello
    Ok(())
}

serde не полагается на механизм отражения во время выполнения (но использует систему признаков Rust ), что устраняет большинство затрат времени исполнения

Для необычных нужд Serde позволяет полностью настроить поведение сериализации путем ручной реализации Serialize/Deserialize свойств для вашего типа.

pub trait Serialize {
    fn serialize< S >(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer;
}

Для просмотра примера реализации компилятором похожей сериализации/десириализации

$  cargo expand 

Следует учитывать три основные категории типов:

  • Последовательности значений (подумайте Vec, срез, кортеж)
  • Сопоставляет ключи со значениями ( HashMap, struct)
  • Все остальное

Поиск неисправностей

the trait serde::ser::Serialize is not implemented for ...

Это почти всегда означает, что вы используете библиотеки, которые зависят от несовместимых версий Serde. Вы можете зависеть от serde 1.0 в вашем Cargo.toml, но использовать какую-то другую библиотеку, которая зависит от serde 0.9. Таким образом, Serialize черта из serde 1.0 может быть реализована, но библиотека ожидает реализации черты Serialize из serde 0.9. С точки зрения компилятора Rust это совершенно разные черты. Исправление заключается в обновлении или понижении версии библиотек по мере необходимости до тех пор, пока версии Serde не совпадут. cargo tree -d Команда полезна для поиска всех мест, куда втягиваются дублирующие зависимости.

Сериализация примитива

impl-serialize

Задача метода fn serialize<T> — взять ваш тип (&self) и сопоставить его с моделью данных Serde, вызвав ровно один из методов данного Serializer

Сериализация примитива:


impl Serialize for i32 {
    fn serialize(&self, serializer: T) -> Result where T: Serializer {
        serializer.serialize_i32(*self)
    }
}
fn main() -> serde_json::Result<()> { 
    let s = 7i32;
    let s_string = serde_json::to_string(&s).unwrap();// Serialize
    println!("serialized = {}", s_string);// 7
}

Сериализация последовательности или map

Составные типы следуют трех этапному процессу: инициализация, элементы, завершение.

use serde::ser::{Serialize, Serializer, SerializeSeq, SerializeMap};

impl<T> Serialize for Vec<T>
where
    T: Serialize,
{
    fn serialize<K>(&self, serializer: K) -> Result<K::Ok, K::Error>
    where
        K: Serializer,
    {
        let mut seq = serializer.serialize_seq(Some(self.len()))?;// инициализация
        for e in self {
            seq.serialize_element(e)?; // элементы
        }
        seq.end() // завершение
    }
}

impl<K, V> Serialize for MyMap<K, V>
where
    K: Serialize,
    V: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(self.len()))?;
        for (k, v) in self {
            map.serialize_entry(k, v)?;
        }
        map.end()
    }
}

Сериализация newtype struct или и unit-структур


#[derive(Debug)]
struct Something(i32);
impl Serialize for Something {
    fn serialize(&self, serializer: T) -> core::result::Result where T: serde::Serializer {
        serializer.serialize_newtype_struct("Something",&self.0)
    }
}
fn main() -> serde_json::Result<()> {  
    let s = Something(25);
    let s_string = serde_json::to_string(&s).unwrap();// Serialize
    println!("serialized = {}", s_string);// 25
}

Сериализация обычные структуры и структуры кортежа

Обычные структуры и структуры кортежа следуют трех этапному процессу init, elements и end

use serde::ser::{Serialize, Serializer, SerializeStruct};
//   1. serialize_struct
//   2. serialize_field
//   3. end
struct Color {
    r: u8,
    g: u8,
    b: u8,
}
impl Serialize for Color {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        // 3 is the number of fields in the struct.
        let mut state = serializer.serialize_struct("Color", 3)?; // init
        state.serialize_field("r", &self.r)?; // elements
        state.serialize_field("g", &self.g)?;// elements
        state.serialize_field("b", &self.b)?;// elements
        state.end() // end
    }
}

use serde::ser::{SerializeTupleStruct};
//   1. serialize_tuple_struct
//   2. serialize_field
//   3. end
struct Point2D(f64, f64);
impl Serialize for Point2D {
    fn serialize<T>(&self, serializer: T) -> Result<T::Ok, S::Error> where T: Serializer {
        // 3 is the number of fields in the struct.
        let mut state = serializer.serialize_tuple_struct("Point2D", 2)?; // init
        state.serialize_field(&self.0)?;// elements
        state.serialize_field(&self.1)?;// elements
        state.end()// end
    }
}
fn main() -> serde_json::Result<()> { 
    let c = Color{r:8,g:9,b:10};
    let c_string = serde_json::to_string(&c).unwrap();// Serialize
    println!("serialized = {}", c_string);// {"r":8,"g":9,"b":10}

    let p = Point2D(8.0,9.1);
    let p_string = serde_json::to_string(&p).unwrap();// Serialize
    println!("serialized = {}", p_string);// [8.0,9.1]
}

Сериализация перечисления


use serde::{Deserialize, Serialize};
use serde_json;
use serde::ser::{Serializer, SerializeStruct, SerializeTupleStruct};

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

enum E {
    // Use three-step process:
    //   1. serialize_struct_variant
    //   2. serialize_field
    //   3. end
    Color { r: u8, g: u8, b: u8 },

    // Use three-step process:
    //   1. serialize_tuple_variant
    //   2. serialize_field
    //   3. end
    Point2D(f64, f64),

    // Use serialize_newtype_variant.
    Inches(u64),

    // Use serialize_unit_variant.
    Instance,
    
    //#[serde(other)] // Обрабатывает любые неизвестные варианты. (Если используется derive) 
    //Unknown,
}

impl Serialize for E {
    fn serialize(&self, serializer: T) -> Result where T: Serializer {
        match self {
            E::Color{r,g,b} =>{
                let mut state = serializer.serialize_struct("Color", 3)?; // init
                state.serialize_field("r", &r)?; // elements
                state.serialize_field("g", &g)?;// elements
                state.serialize_field("b", &b)?;// elements
                state.end() // end
            }
            E::Point2D(l,r) =>{ 
                // 3 is the number of fields in the struct.
                let mut state = serializer.serialize_tuple_struct("Point2D", 2)?; // init
                state.serialize_field(&l)?;// elements
                state.serialize_field(&r)?;// elements
                state.end()// end                
            }
            E::Inches(v) =>{
                serializer.serialize_newtype_struct("Inches",&v)
                //serializer.serialize_u64(*v)
            }
            E::Instance =>{
                serializer.serialize_unit_variant("E", 3, "Instance")  // "\"Instance\""
                //serializer.serialize_unit_struct("Instance") // null
                //serializer.serialize_str("Instance")  // "Instance"
            }
            //E::Unknown => serializer.serialize_unit_variant("E", 4, "Unknown")
            _ => serializer.serialize_unit_variant("E", 4, "Unknown")
        }
    }
}
fn main() {
    let object = E::Color{r:1u8,g:2u8,b:3u8};
    let enum_str:String = serde_json::to_string(&object).unwrap();// Serialize
    assert_eq!("{\"r\":1,\"g\":2,\"b\":3}", enum_str);
    /*
    Если вы хотите сериализовать данные в формате, где ключи не заключаются в кавычки, то JSON не подходит. Вы можете:
    1.Использовать другой формат, например, YAML или XML, которые позволяют более гибкое представление структуры.
    2.Настроить собственную сериализацию для вашего объекта и вручную формировать строку, исключая кавычки вокруг ключей.
    impl E {
        fn to_custom_format(&self) -> String {
            match self {
                E::Color { r, g, b } => { format!("Color: {{r: {}, g: {}, b: {}}}", r, g, b) }
                ...
    }}}
    let enum_str = object.to_custom_format();
    */
    let object = E::Point2D(1f64,2f64);
    let enum_str:String = serde_json::to_string(&object).unwrap();// Serialize
    assert_eq!("[1.0,2.0]", enum_str);
    
    let object = E::Inches(8u64);
    let enum_str:String = serde_json::to_string(&object).unwrap();// Serialize
    assert_eq!("8", enum_str);
    
    let object = E::Instance;
    let enum_str:String = serde_json::to_string(&object).unwrap();// Serialize
    assert_eq!("\"Instance\"", enum_str);
}

Serialize enum as number

enum-number

[dependencies]
serde = "1.0"
serde_json = "1.0"
serde_repr = "0.1"

use serde_repr::*;

#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrime {
    Two = 2,
    Three = 3,
    Five = 5,
    Seven = 7,
}
fn main() {
    use SmallPrime::*;
    let nums = vec![Two, Three, Five, Seven];

    // Prints [2,3,5,7]
    println!("{}", serde_json::to_string(&nums).unwrap());
    assert_eq!(Two, serde_json::from_str("2").unwrap());
}

Сериализация типов обернутых в Option


use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct MyStruct {
    name: String,
    age: Option,
}

fn main() -> Result<(), Box> {
    let person_with_age = MyStruct {
        name: "Alice".to_string(),
        age: Some(30),
    };

    let person_without_age = MyStruct {
        name: "Bob".to_string(),
        age: None,
    };

    // Сериализация
    let serialized_with_age = serde_json::to_string(&person_with_age)?;
    let serialized_without_age = serde_json::to_string(&person_without_age)?;

    println!("Serialized with age: {}", serialized_with_age);
    println!("Serialized without age: {}", serialized_without_age);

    // Десериализация
    let deserialized_with_age: MyStruct = serde_json::from_str(&serialized_with_age)?;
    let deserialized_without_age: MyStruct = serde_json::from_str(&serialized_without_age)?;

    println!("Deserialized with age: {:?}", deserialized_with_age);
    println!("Deserialized without age: {:?}", deserialized_without_age);

    Ok(())
}

Кастомная сериализация с Option


use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::ser::{SerializeStruct, SerializeTupleStruct};
use serde::de::{self, Visitor};
use std::fmt;

#[derive(Debug)]
struct MyStruct {
    name: String,
    age: Option,
}
impl Serialize for MyStruct {
    fn serialize(&self, serializer: T) -> Result where T: Serializer {
        let mut state = serializer.serialize_struct("MyStruct", 2)?;
        state.serialize_field("name", &self.name)?;
        // Кастомная сериализация Option
        match &self.age {
            Some(age) => state.serialize_field("age", age)?,
            None => state.serialize_field("age", "")?, // Сериализуем None как пустую строку
        }
        state.end()
    }
}
impl<'de> Deserialize<'de> for MyStruct {
    fn deserialize(deserializer: D) -> Result
    where
        D: Deserializer<'de>,{
        struct MyStructVisitor;

        impl<'de> Visitor<'de> for MyStructVisitor {
            type Value = MyStruct;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a struct representing a person")
            }

            fn visit_map(self, mut map: V) -> Result
            where
                V: de::MapAccess<'de>,
            {
                let mut name = None;
                let mut age = None;

                while let Some(key) = map.next_key()? {
                    match key {
                        "name" => {
                            if name.is_some() {
                                return Err(de::Error::duplicate_field("name"));
                            }
                            name = Some(map.next_value()?);
                        }
                        "age" => {
                            // Кастомная десериализация: если age пустая строка, интерпретируем как None
                            let val: String = map.next_value()?;
                            age = if val.is_empty() {
                                None
                            } else {
                                Some(val.parse().unwrap()) // Преобразуем строку в число
                            };
                        }
                        _ => {
                            let _: serde::de::IgnoredAny = map.next_value()?;
                        }
                    }
                }
                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
                Ok(MyStruct { name, age })
            }
        }
        deserializer.deserialize_struct("MyStruct", &["name", "age"], MyStructVisitor)
    }
}
fn main() -> Result<(), Box> {
    let person_with_age = MyStruct {
        name: "Alice".to_string(),
        age: Some(30),
    };
    let person_without_age = MyStruct {
        name: "Bob".to_string(),
        age: None,
    };
    let serialized_with_age = serde_json::to_string(&person_with_age)?;
    let serialized_without_age = serde_json::to_string(&person_without_age)?;
    println!("Serialized with age: {}", serialized_with_age);
    println!("Serialized without age: {}", serialized_without_age);

    let deserialized_with_age: MyStruct = serde_json::from_str(&serialized_with_age)?;
    let deserialized_without_age: MyStruct = serde_json::from_str(&serialized_without_age)?;
    println!("Deserialized with age: {:?}", deserialized_with_age);
    println!("Deserialized without age: {:?}", deserialized_without_age);
    Ok(())
}

Задача этого метода — сопоставить тип с моделью данных Serde, предоставив десериализатору Visitor, который может управляться десериализатором для создания экземпляра вашего типа. Это достигается с помощью трейта Deserialize и создания специального визитера (Visitor), который отвечает за преобразование данных из строки, чисел, массивов или объектов в ваш тип.

pub trait Deserialize<'de>: Sized {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>;
}

Когда нужно использовать ручную десериализацию?

Если входной формат не соответствует стандартной структуре JSON или YAML. Если вы хотите добавить специфическую логику обработки данных, например:

  • Игнорирование полей.
  • Преобразование типов (например, строка в число).
  • Обработка дублирующихся ключей или неизвестных значений.

Примеры некоторых методов deserialize_*

Примитивные типы:

  • deserialize_bool
  • deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_i128
  • deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_u128
  • deserialize_f32, deserialize_f64
  • deserialize_char, deserialize_str

Сложные типы:

  • deserialize_bytes
  • deserialize_option
  • deserialize_seq
  • deserialize_map
  • deserialize_struct
  • deserialize_enum

Другие:

  • deserialize_unit (для типа ())
  • deserialize_unit_struct
  • deserialize_newtype_struct
  • deserialize_tuple
  • deserialize_any (для самоописательных форматов)

Два способа реализовать Deserializer

trait.Deserializer

1. Через метод deserialize_any. Форматы данных с самоописанием, такие как JSON, YAML, XML, позволяют просматривать сериализованные данные и определять, что они представляют. Например: понять их тип (например, строка, число, карта, массив и т. д.) {} — это карта (map), [] — это массив (sequence), "..." — это строка (string). Если формат данных поддерживает Deserializer::deserialize_any, он будет управлять Visitor. JSON использует этот подход при десериализации serde_json::Value, который представляет собой перечисление, которое может представлять любой документ JSON.В зависимости от входных данных будет вызван Deserializer один из методов Visitor Когда вы десериализуете в тип serde_json::Value, используется deserialize_any


fn main(){
     let json_data = r#"{ "key": "value", "number": 42 }"#;
    // Десериализация в Value через deserialize_any
    let value: serde_json::Value = serde_json::from_str(json_data)?;
}

2. Через конкретные методы deserialize_* для конкретных типов. Эти методы используются для форматов без самоописания, таких как Postcard, Bincode, или MessagePack. Форматы без самоописания не способны десериализовать что-то вроде serde_json::Value

Как написать Serde Visitor для преобразования массива массивов строк в Vec<Vec<f64>>


extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use serde::de::{Deserialize, Deserializer, Error, Unexpected};

#[derive(Debug, Deserialize)]
struct Payload {
    #[serde(default)]
    values: Vec>,
}

#[derive(Debug)]
struct Value(f64);

impl<'de> Deserialize<'de> for Value {
    fn deserialize(deserializer: D) -> Result
        where D: Deserializer<'de>
    {
        let s: &str = Deserialize::deserialize(deserializer)?;
        s.parse()
            .map(Value)
            .map_err(|_| D::Error::invalid_value(Unexpected::Str(s), &"a floating point number as a string"))
    }
}
fn main() {
    let input = r#"
{
  "values": [["2", "1.4"], ["8.32", "1.5"]]
}
"#;

Десериализация структуры вручную из JSON (данных с самоописанием) с помошью deserialize_* или deserialize_any


use serde::de::{self, Deserializer, Visitor, MapAccess};
use serde::Deserialize;
use std::fmt;

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

// Реализуем Deserialize вручную
impl<'de> Deserialize<'de> for Person {
    fn deserialize(deserializer: D) -> Result
    where
        D: Deserializer<'de>,
    {
        // Создаем визитер для обработки данных
        struct PersonVisitor;

        impl<'de> Visitor<'de> for PersonVisitor {
            type Value = Person;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a map with keys `name` and `age`")
            }

            fn visit_map(self, mut map: M) -> Result
            where
                M: MapAccess<'de>,
            {
                // При инициализации с None, компилятор оставляет тип этих переменных неявным Option
                // let mut name = None::;
                // let mut age = None::;
               let mut name = None;
               let mut age = None;

                while let Some(key) = map.next_key::()? {
                    match key.as_str() {
                        "name" => {
                            if name.is_some() {
                                return Err(de::Error::duplicate_field("name"));
                            }
                            name = Some(map.next_value()?);
                        }
                        "age" => {
                            if age.is_some() {
                                return Err(de::Error::duplicate_field("age"));
                            }
                            age = Some(map.next_value()?);
                        }
                        _ => {
                            let _: de::IgnoredAny = map.next_value()?; // Игнорируем неизвестные поля
                        }
                    }
                }

                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
                let age = age.ok_or_else(|| de::Error::missing_field("age"))?;

                Ok(Person { name, age })
            }
        }

        // Запускаем десериализацию с нашим визитером
        // deserialize_struct строго следует струтуре выходного обьекта
        // const FIELDS: &[&str] = &["name", "age"];
        // deserializer.deserialize_struct("Person", FIELDS, PersonVisitor)
        
       // но можно и через метод deserialize_any так как тип JSON самоописывающийся
       // deserializer.deserialize_any(PersonVisitor)

        // deserialize_map более гибок чем deserialize_struct, и может "на лету" добавлять динамические поля
        deserializer.deserialize_map(PersonVisitor)
    }
}

fn main() -> Result<(), Box> {
    let json = r#"{"name": "Alice", "age": 30}"#;

    // Десериализуем JSON в структуру
    let person: Person = serde_json::from_str(json)?;
    println!("{:?}", person);

    Ok(())
}

Десериализация структуры вручную из JSON (данных с самоописанием) с помошью deserialize_* или deserialize_any

Если поле age в JSON может быть как числом, так и строкой, содержащей число, вам нужно учесть оба возможных формата при десериализации. Для этого можно использовать метод map.next_value с оберткой над обработчиком значений.


use serde::de::{self, Deserializer, Visitor, MapAccess};
use std::fmt;

// Ваша структура
#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}
// Реализация Deserialize для Person
impl<'de> serde::Deserialize<'de> for Person {
    fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> {
        deserializer.deserialize_any(PersonVisitor)
    }
}

// Посетитель для десериализации структуры Person
struct PersonVisitor;

impl<'de> Visitor<'de> for PersonVisitor {
    type Value = Person;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a map representing a Person")
    }
    fn visit_map(self, mut map: M) -> Result where M: MapAccess<'de> {
        let mut name = None;
        let mut age = None;

        while let Some(key) = map.next_key::()? {
            match key.as_str() {
                "name" => {
                    name = Some(map.next_value()?);
                }
                "age" => {
                    age = Some(map.next_value::()?.0);
                }
                _ => {
                    // Пропускаем неизвестные ключи
                    let _ = map.next_value::()?;
                }
            }
        }
        // Убедимся, что все обязательные поля есть
        let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
        let age = age.ok_or_else(|| de::Error::missing_field("age"))?;
        Ok(Person { name, age })
    }
}

// Обертка для десериализации age как числа или строки
struct FlexibleU32(u32);

impl<'de> serde::Deserialize<'de> for FlexibleU32 {
    fn deserialize(deserializer: D) -> Result
    where
        D: Deserializer<'de>,
    {
        struct FlexibleU32Visitor;

        impl<'de> Visitor<'de> for FlexibleU32Visitor {
            type Value = FlexibleU32;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("an integer or a string containing an integer")
            }

            fn visit_u64(self, value: u64) -> Result where E: de::Error {
                Ok(FlexibleU32(value as u32))
            }

            fn visit_str(self, value: &str) -> Result where E: de::Error {
                value
                    .parse::()
                    .map(FlexibleU32)
                    .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(value), &self))
            }
        }
        deserializer.deserialize_any(FlexibleU32Visitor)
    }
}
fn main() -> serde_json::Result<()> {
    let json1 = r#"{"name": "John", "age": 30}"#;
    let json2 = r#"{"name": "Alice", "age": "25"}"#;
    let person1: Person = serde_json::from_str(json1)?;
    let person2: Person = serde_json::from_str(json2)?;
    println!("{:?}", person1);
    println!("{:?}", person2);
    Ok(())
}

Десериализация перечисления из JSON с помощью deserialize_*


use serde::de::{self, Deserializer, Visitor, MapAccess};
use serde::Deserialize;
use std::fmt;

#[derive(Debug)]
enum Command {
    Start,
    Stop,
    Unknown,
}

// Реализуем Deserialize для перечисления
impl<'de> Deserialize<'de> for Command {
    fn deserialize(deserializer: D) -> Result
    where
        D: Deserializer<'de>,
    {
        struct CommandVisitor;

        impl<'de> Visitor<'de> for CommandVisitor {
            type Value = Command;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a valid command string")
            }
            fn visit_str(self, value: &str) -> Result
            where
                E: de::Error,
            {
                match value {
                    "Start" => Ok(Command::Start),
                    "Stop" => Ok(Command::Stop),
                    _ => Ok(Command::Unknown), // Обрабатываем неизвестные команды
                }
            }
        }
        deserializer.deserialize_str(CommandVisitor)
    }
}
fn main() -> Result<(), Box> {
    let json = r#""Start""#;
    let command: Command = serde_json::from_str(json)?;
    println!("{:?}", command);
    Ok(())
}

deserialize_map

deserialize_map

Использование deserialize_map вместо deserialize_struct дает большую гибкость за счет того, что этот метод не накладывает жестких требований на структуру входных данных.

  1. Динамические или неизвестные поля С deserialize_map вы можете динамически прочитать все поля и сохранить их, например, в HashMap или игнорировать ненужные:
while let Some(key) = map.next_key::<String>()? {
    match key.as_str() {
        "name" => name = Some(map.next_value()?),
        "age" => age = Some(map.next_value()?),
        _ => {
            // Сохраняем дополнительные поля
            extra_fields.insert(key, map.next_value()?);
        }
    }
}
  1. Обработка неизвестных структур Если вы работаете с данными, структура которых заранее неизвестна, deserialize_map предоставляет возможность анализировать ключи и значения на лету.
{
    "type": "person",
    "data": {
        "name": "John",
        "age": 30
    }
}

Вы можете обработать ключ type, чтобы решить, какую структуру десериализовать дальше.

  1. Пропуск или обработка неизвестных ключей С помощью deserialize_map вы можете легко игнорировать ключи, которые вам не нужны.
#![allow(unused)]

fn main() {
match key.as_str() {
    "name" => name = Some(map.next_value()?),
    "age" => age = Some(map.next_value()?),
    _ => {
        let _ = map.next_value::()?; // Игнорируем поле
    }
}
}
  1. Работа с вложенными структурами без явных определений Если вложенные объекты имеют произвольный или переменный формат, deserialize_map позволяет обработать их без создания соответствующих структур
fn main(){
    let data: HashMap<String, serde_json::Value> = map.next_value()?;
}

deserialize_map


use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess};
use std::fmt;

struct MyMap {
    data: std::collections::HashMap,
}

impl<'de> Deserialize<'de> for MyMap {
    fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> {
        deserializer.deserialize_map(MyMapVisitor)
    }
}
struct MyMapVisitor;

impl<'de> Visitor<'de> for MyMapVisitor {
    type Value = MyMap;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a map of string keys and string values")
    }
    fn visit_map(self, mut map: M) -> Result where M: MapAccess<'de> {
        let mut data = std::collections::HashMap::new();
        while let Some((key, value)) = map.next_entry::()? {
            data.insert(key, value);
        }
        Ok(MyMap { data })
    }
}
fn main() -> serde_json::Result<()> {
    let json = r#"{"key1": "value1", "key2": "value2"}"#;
    let my_map: MyMap = serde_json::from_str(json)?;
    println!("Deserialized map: {:?}", my_map.data);
    Ok(())
}

Десериализация и буферизация

Используя BufReader и BufWriter, мы можем амортизировать стоимость системных вызовов.

unbuffered-io-slows-rust-programs

Проблемы производительности могут легко проявиться в программах на Rust, когда буферизация не используется. Возьмем, к примеру, serde_json, библиотеку для чтения и записи данных в JSON с простым в использовании интерфейсом. Его from_reader() функция принимает любой объект, реализующий Read признак, и декодирует байты в дерево JSON. В File орудии типа Read признак, так что мы можем очень легко расшифровать файл на диске. Вот простая программа, которая делает это, и она File намеренно не заключена в BufReader объект.


use std::{fs, io};
fn main() -> io::Result<()> {
    let mut f = fs::File::open("sample.json")?;
    let v: serde_json::Value = serde_json::from_reader(&mut f).unwrap();
    println!("{}", v.is_object());
    return Ok(());
}

Мы можем использовать, perf чтобы подсчитать, сколько системных вызовов read() было сделано при выполнении этой программы.

$ sudo perf stat -e syscalls:sys_enter_read ./target/release/04_unbuffered_json
 Performance counter stats for './target/release/04_unbuffered_json':
         2,009,119      syscalls:sys_enter_read

Размер файла sample.json составляет 2009 108 байт. Чтобы десериализовать файл, serde_json выполняет один системный вызов на каждый байт! (Дополнительные 11 системных вызовов read() происходят в начале программы для загрузки libc и т. Д.) Наш надежный партнер strace подтверждает, что это так.

$ strace --trace=read ./target/release/04_unbuffered_json
...
read(3, "{", 1)                         = 1
read(3, "\"", 1)                        = 1
read(3, "t", 1)                         = 1
read(3, "y", 1)                         = 1
read(3, "p", 1)                         = 1
read(3, "e", 1)                         = 1
read(3, "\"", 1)                        = 1
read(3, ":", 1)                         = 1
...

Когда мы исправляем программу, помещая наш файл внутрь буферизованного ридера, результаты поразительны. Мы уменьшаем количество системных вызовов почти в 8000 раз - что имеет большой смысл, потому что мы читаем 8192 байта за раз вместо одного - и программа работает в 11 раз быстрее.


use std::{fs, io};
fn main() -> io::Result<()> {
    let mut f = BufWriter::new(fs::File::open("sample.json")?);
    let v: serde_json::Value = serde_json::from_reader(&mut f).unwrap();
    println!("{}", v.is_object());
    return Ok(());
}
$ sudo perf stat -e syscalls:sys_enter_read ./target/release/05_buffered_json
 Performance counter stats for './target/release/05_buffered_json':
               257      syscalls:sys_enter_read
$ strace --trace=read ./target/release/05_buffered_json
...
read(3, "{\"type\":\"FeatureCollection\",\"crs"..., 8192) = 8192
read(3, "6200000000001}},{\"type\":\"Feature"..., 8192) = 8192
read(3, "egion\":\"AK\",\"category\":\"In-betwe"..., 8192) = 8192
read(3, "01}},{\"type\":\"Feature\",\"id\":95,\""..., 8192) = 8192
...

$ hyperfine -w 5 -m 30 \
    ./target/release/04_unbuffered_json \
    ./target/release/05_buffered_json
Benchmark #1: ./target/release/04_unbuffered_json
  Time (mean ± σ):     326.3 ms ±   8.1 ms    [User: 70.2 ms, System: 256.0 ms]
  Range (min … max):   312.2 ms … 346.8 ms    30 runs

Benchmark #2: ./target/release/05_buffered_json
  Time (mean ± σ):      28.5 ms ±   1.4 ms    [User: 22.9 ms, System: 5.6 ms]
  Range (min … max):    26.2 ms …  33.2 ms    106 runs

Summary
  './target/release/05_buffered_json' ran
   11.43 ± 0.63 times faster than './target/release/04_unbuffered_json'

Понимание времени жизни lifetimes десериализатора

serde.rs/lifetimes

implementation-of-deserialize-is-not-general-enough

В общем не получится Deserialize структуру с lifetime не имея во владении данные для нее


fn main(){
 let mut file = std::fs::File::open("example.json").unwrap();
 let mut strbuf = String::new();
 file.read_to_string(&mut strbuf).unwrap();
 let result: SshConfig = serde_json::from_str(&strbuf).unwrap();
 println!("{:?}", result.username);
}

use serde::{Serialize, Deserialize};

type StaticStr = &'static str;
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(try_from = "RawFoo")]
struct FooWithStatic {
    name: StaticStr,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct RawFoo {
    name: String,
}

struct FooNotFound;

impl std::fmt::Display for FooNotFound {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Foo not found!")
    }
}
impl TryFrom for FooWithStatic {
    type Error = FooNotFound;
    
    fn try_from(raw_foo: RawFoo) -> Result {
        match raw_foo.name.as_str() {
            "foo" => Ok(FooWithStatic { name: &"foo" }),
            "bar" => Ok(FooWithStatic { name: &"bar" }),
            "baz" => Ok(FooWithStatic { name: &"baz" }),
            _ => Err(FooNotFound)
        }
    }
}
fn main() {
    let foo = FooWithStatic { name: "foo" };
    let serialized = serde_json::to_value(&foo).unwrap();
    let deserialized: FooWithStatic = serde_json::from_value(serialized).unwrap();
    assert_eq!(foo, deserialized);
}
//    Compiling playground v0.0.1 (/playground)
// error: implementation of `Deserialize` is not general enough
//   --> src/main.rs:38:39
//    |
// 38 |     let deserialized: FooWithStatic = serde_json::from_value(serialized).unwrap();
//    |                                       ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
//    |
//    = note: `FooWithStatic` must implement `Deserialize<'0>`, for any lifetime `'0`...
//    = note: ...but it actually implements `Deserialize<'static>`
// error: could not compile `playground` due to previous error

Deserialize струтуру с lifetime

Serde не сможет напрямую сериализовать и десериализовать структуры, содержащие время жизни (например, структуры с полем типа &'a str), если используется стандартный подход с #[derive(Serialize, Deserialize)]. Это связано с тем, что Serde не поддерживает работу с типами, содержащими ссылки с ограниченным временем жизни, так как она не может безопасно управлять временем жизни этих ссылок во время (де)сериализации.

Если вам необходимо сохранить ссылки с временем жизни в структуре, вы должны сами реализовать логику сериализации и десериализации с использованием Serializer и Deserializer вручную.


use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::de::{self, Visitor};
use std::fmt;
use serde::ser::SerializeStruct;

#[derive(Debug, PartialEq)]
struct Struct<'a> {
    name: &'a str,
    age: u32,
}

// Реализация сериализации для Struct
impl<'a> Serialize for Struct<'a> {
    fn serialize(&self, serializer: T) -> Result where T: Serializer {
        // Сериализация структуры как карты (map)
        let mut state = serializer.serialize_struct("Struct", 2)?;
        state.serialize_field("name", &self.name)?;
        state.serialize_field("age", &self.age)?;
        state.end()
    }
}

// Реализация десериализации для Struct
impl<'a> Deserialize<'a> for Struct<'a> {
    fn deserialize(deserializer: D) -> Result
    where
        D: Deserializer<'a>,
    {
        // Для десериализации создаем Visitor
        struct StructVisitor;

        impl<'a> Visitor<'a> for StructVisitor {
            type Value = Struct<'a>;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "a struct with fields `name` and `age`")
            }

            fn visit_map(self, mut map: V) -> Result
            where
                V: de::MapAccess<'a>,
            {
                let mut name = None;
                let mut age = None;

                // Обрабатываем поля
                while let Some(key) = map.next_key()? {
                    match key {
                        "name" => {
                            if name.is_some() {
                                return Err(de::Error::duplicate_field("name"));
                            }
                            name = Some(map.next_value()?);
                        }
                        "age" => {
                            if age.is_some() {
                                return Err(de::Error::duplicate_field("age"));
                            }
                            age = Some(map.next_value()?);
                        }
                        _ => { map.next_value::()?; } // Пропускаем неизвестные поля
                    }
                }
                // Проверяем, что все обязательные поля были найдены
                let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
                let age = age.ok_or_else(|| de::Error::missing_field("age"))?;

                Ok(Struct { name, age })
            }
        }
        // Начинаем десериализацию через Visitor
        deserializer.deserialize_struct("Struct", &["name", "age"], StructVisitor)
    }
}
fn main() {
    // Пример структуры
    let original = Struct {
        name: "Alice",
        age: 30,
    };
    // Сериализация
    let serialized = serde_json::to_string(&original).unwrap();
    println!("Serialized: {}", serialized);
    // Десериализация
    let deserialized: Struct = serde_json::from_str(&serialized).unwrap();
    println!("Deserialized: {:?}", deserialized);
    // Проверка
    assert_eq!(original, deserialized);
}

Для форматов без самоописания, таких как Postcard, Bincode, MessagePack

Десериализация структуры в ручную из Bincode с помощью deserialize_*


use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess};
use serde::Serialize;
use std::fmt;

#[derive(Serialize, Debug)]
struct Person {
    name: String,
    age: u8,
}

impl<'de> Deserialize<'de> for Person {
    fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> {
        struct PersonVisitor;

        impl<'de> Visitor<'de> for PersonVisitor {
            type Value = Person;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a struct representing a Person")
            }
            fn visit_seq(self, mut seq: V) -> Result where V: SeqAccess<'de> {
                let name: String = seq
                    .next_element()?
                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
                let age: u8 = seq
                    .next_element()?
                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
                Ok(Person { name, age })
            }
        }
        // метод deserialize_map не поддерживается форматом Bincode так как в данных отсутвуют ключи, 
        // есть только последовательность данных
        deserializer.deserialize_struct("Person", &["name", "age"], PersonVisitor)
    }
}
fn main() -> Result<(), Box> {
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
    };
    // Сериализация в формат Bincode
    let serialized: Vec = bincode::serialize(&person)?;// [5, 0, 0, 0, 0, 0, 0, 0, 65, 108, 105, 99, 101, 30]
    println!("Serialized data: {:?}", serialized);
    // Десериализация из формата Bincode
    let deserialized: Person = bincode::deserialize(&serialized)?;
    println!("Deserialized struct: {:?}", deserialized);
    Ok(())
}

Custom Deserialize struct


use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess, MapAccess};

#[derive(serde::Serialize,Debug)]
struct Something {
    val: i32
}

impl<'de> Deserialize<'de> for Something {
    fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>{
        
        enum Field { Val }
        impl<'de> Deserialize<'de> for Field {
            fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> {

                struct FieldVisitor;
                impl<'de> Visitor<'de> for FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                        formatter.write_str("`val`")
                    }
                    fn visit_str(self, value: &str) -> Result where E: de::Error {
                        match value {
                            "val" => Ok(Field::Val),
                            _ => Err(de::Error::unknown_field(value, FIELDS)),
                        }
                    }
                    fn visit_bytes(self,value: &[u8]) -> Result where E: serde::de::Error {
                        match value {
                            b"min" => Ok(Field::Val),
                             _ => Err(de::Error::custom(format_args!("unknown field"))),
                        }
                    }
                }
                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        //struct SomethingVisitor;
        struct SomethingVisitor<'de> {
            marker: std::marker::PhantomData,
            lifetime: std::marker::PhantomData<&'de ()>,
        }
        // Реализация поддерживает два возможных способа представления структуры в формате данных: в виде последовательности visit_seq, как в Postcard,
        //  и в виде карты visit_map , как в JSON
        impl<'de> Visitor<'de> for SomethingVisitor<'de> {
            type Value = Something;
        
            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 
                formatter.write_str("struct Something")
            }
            fn visit_seq(self, mut seq: V) -> Resultwhere V: SeqAccess<'de> {
                let val = seq.next_element()?
                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
                Ok(Something{val})
            }
            fn visit_map(self, mut map: V) -> Result where V: MapAccess<'de> {
                let mut val = None;
                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Val => {
                            if val.is_some() {
                                return Err(de::Error::duplicate_field("val"));
                            }
                            val = Some(map.next_value()?);
                        }
                    }
                }
                let val = val.ok_or_else(|| de::Error::missing_field("val"))?;
                Ok(Something{val})
            }
        } 
        const FIELDS: &'static [&'static str] = &["val"];
        serde::Deserializer::deserialize_struct(deserializer,"Something", FIELDS,
          SomethingVisitor {
            marker: std::marker::PhantomData::,
            lifetime: std::marker::PhantomData,
         })
    }
}
fn main() -> serde_json::Result<()>{
    let s_string = r#"{"val": 123}"#;
    let l: Something = serde_json::from_str(&s_string)?;// Deserialize
    println!("deserialized = {:?}", &l);// LongString { val: 123 }

    let l_string = b"{\"val\": 123}";
    let l: Something = serde_json::from_slice(l_string)?;// Deserialize
    println!("deserialized = {:?}", &l);// LongString { val: 123 }

    let v:serde_json::Value =  serde_json::json!({"val": 123});
    let l: Something = serde_json::from_value(v).unwrap();// Deserialize
    println!("deserialized = {:?}", &l);// LongString { val: 123 }   

    Ok(())
}

Десериализация с проверкой валидации типа и с возвратом ошибки

#[derive(Debug)]
struct Item(u64);

impl Item {
    fn new(n:u64) -> Option<Item> {
        if n < 10 {
           return None;
        }
        Some(Item(n))
    }
}
impl<'de> Deserialize<'de> for Item {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
        Deserialize::deserialize(deserializer)
        .map(|v:serde_json::Value|{
           //v.as_str().unwrap_or_default().to_string()
            v.as_str().map(|s:&str|{s.to_string()})//.unwrap_or_default()
        })
       .and_then(|res|{
           res.ok_or(serde::de::Error::custom("Value error as_str"))
       })
        .and_then(|s:String|{
             s.parse::<u64>()
                 .map_err(|_e|serde::de::Error::custom("Can't parse u64 "))
        })
        .and_then(|n:u64|{
            Item::new(n).ok_or(serde::de::Error::custom("n < 10"))
        })
    }
}
fn main(){
    let deserialized:Item  = serde_json::from_str("\"11\"").unwrap();
    println!("{:?}",deserialized); 
}

Не учитывая валидацию типа

use std::fmt::Display;
use std::str::FromStr;
#[derive(Deserialize,Debug)]
struct Item(#[serde(deserialize_with = "from_str")] u64);
fn from_str<'de, T, D>(deserializer: D) -> Result<T, D::Error>
    where T: FromStr,
          T::Err: Display,
          D: Deserializer<'de>
{
    let s = String::deserialize(deserializer)?;
    T::from_str(&s).map_err(de::Error::custom)
}

это гибкая, быстрая и универсальная платформа двоичной сериализации (без Visitor)

musli ориентирован на максимальную производительность при сериализации и десериализации:

  • Оптимизация для низкоуровневых форматов данных.
  • Упрощённый API, который минимизирует накладные расходы и выделения памяти.
  • Часто быстрее, чем serde, для сериализации и десериализации в бинарных форматах, благодаря минимизации проверок и дополнительного кода.

Когда важно: если ваша программа сильно зависит от скорости сериализации/десериализации, например, при обработке больших массивов данных или работе с высокоскоростными системами (например, сетевыми протоколами).


use musli::{Encode, Decode};
use musli_utils::options::{self, Options, Integer};
use musli_storage::Encoding;

const OPTIONS: Options = options::new().with_integer(Integer::Fixed).build();
const CONFIG: Encoding = Encoding::new().with_options();

#[derive(Debug, PartialEq, Encode, Decode)]
struct Struct<'a> {
    name: &'a str,
    age: u32,
}
fn main(){
    let mut out = Vec::new();

    let object = Struct {
        name: "Aristotle",
        age: 61,
    };

    CONFIG.encode(&mut out, &object).unwrap();
    println!("Serialized data: {:?}", out);

    let deserialized: Struct<'_> = CONFIG.decode(&out[..]).unwrap();
    println!("{:?}",deserialized);
    assert_eq!(object, deserialized);
}

rkyv( архив ) — еще одна альтернативная платформа сериализации/десериализации, полностью ориентированная на операции нулевого копирования. Она позволяет сериализовать данные в компактное представление и работать с ними напрямую без предварительной десериализации. (В serde данные всегда нужно десериализовать в структуру Rust перед использованием.)

В отличие от serde, rkyv создает данные, десериализация которых гарантирована. Если вы записали свои данные на диск, вы можете просто mmap перенести файл в память, указать указатель, и ваши данные готовы к использованию. Это делает его идеальным для высокопроизводительных приложений, связанных с вводом-выводом.

Хотя rkyv — отличный формат для окончательных данных, в нем отсутствует полноценная система схем, и он недостаточно приспособлен для миграции данных и обновления схемы. rkyv работает только с типами, которые реализуют определённые трейты (Archive, Serialize, Deserialize), что иногда требует дополнительной работы.

Если ваш вариант использования требует этих возможностей, вам могут потребоваться дополнительные библиотеки для создания этих функций поверх rkyv. Вы можете использовать другие платформы сериализации, такие как serde, с теми же типами, что и rkyv, без конфликтов.

Когда выбрать rkyv?

Производительность критична: Для приложений, где требуется максимально быстрая сериализация и особенно десериализация (например, игровые движки, системы реального времени).

Большие объёмы данных: Если вы работаете с большими структурами, которые нужно читать напрямую из памяти без затрат на десериализацию.

Ограниченные ресурсы: В системах с ограниченной памятью или мощностью процессора (например, встраиваемые системы).

Иммутабельность данных: Если сериализованные данные редко изменяются и чаще читаются.


use rkyv::{deserialize, rancor::Error, Archive, Deserialize, Serialize};

#[derive(Archive, Deserialize, Serialize, Debug, PartialEq)]
#[rkyv(
    // This will generate a PartialEq impl between our unarchived
    // and archived types
    compare(PartialEq),
    // Derives can be passed through to the generated type:
    derive(Debug),
)]
struct Test {
    int: u8,
    string: String,
    option: Option>,
}

fn main() {
    let value = Test {
        int: 42,
        string: "hello world".to_string(),
        option: Some(vec![1, 2, 3, 4]),
    };

    // Serializing is as easy as a single function call
    let _bytes = rkyv::to_bytes::(&value).unwrap();

    // Or you can customize your serialization for better performance or control
    // over resource usage
    use rkyv::{api::high::to_bytes_with_alloc, ser::allocator::Arena};

    let mut arena = Arena::new();
    let bytes =
        to_bytes_with_alloc::<_, Error>(&value, arena.acquire()).unwrap();

    // You can use the safe API for fast zero-copy deserialization
    let archived = rkyv::access::(&bytes[..]).unwrap();
    assert_eq!(archived, &value);

    // Or you can use the unsafe API for maximum performance
    let archived =
        unsafe { rkyv::access_unchecked::(&bytes[..]) };
    assert_eq!(archived, &value);

    // And you can always deserialize back to the original type
    let deserialized = deserialize::(archived).unwrap();
    assert_eq!(deserialized, value);
}