serdeはserializeとdeserializeを行うクレートです。
関数を呼んで機能を実現する「わかりやすいライブラリ」ではなく、インターフェースというか、プロトコルというか、1段メタな機能を実現するツールであるように思います。attributeで目印をつけ、たとえばserde_jsonという別クレートで実際のシリアライズ・デシリアライズを行うと理解しています。
以下、jsonとstructの相互変換を行う例を雑にまとめてみます。
必要クレート
serde = { version = "1.0.130", features = ["derive"] } serde_json = "1.0.68"
準備
use serde::{Deserialize, Serialize}; use std::fs; #[derive(Serialize, Deserialize, Debug)] struct Person { name: String, age: u8, }
structからJSON
serde_json::to_writer(&mut file, &p)
JSONからstruct
serde_json::from_reader::<std::fs::File, Person>
もしくは
serde_json::from_str::<Person>(&content)
全体
use serde::{Deserialize, Serialize}; use std::fs; const JSON_FILE_NAME: &str = "person.json"; #[derive(Serialize, Deserialize, Debug)] struct Person { name: String, age: u8, } fn gen_json() { let json = r#" { "name": "John Doe", "age": 43 } "#; let p: Person = serde_json::from_str(json).unwrap(); // save to file let mut file = std::fs::File::create(JSON_FILE_NAME).unwrap(); serde_json::to_writer(&mut file, &p).unwrap(); println!("{:?}", p); } fn read_json_fs() { let file = std::fs::File::open(JSON_FILE_NAME).unwrap(); match serde_json::from_reader::<std::fs::File, Person>(file) { Ok(p) => println!("{:?}", p), Err(e) => println!("error: {}", e), } } fn read_json_str() { let content = fs::read_to_string(JSON_FILE_NAME).unwrap(); match serde_json::from_str::<Person>(&content) { Ok(p) => println!("{:?}", p), Err(e) => println!("error: {}", e), } } fn main() { // gen_json(); read_json_fs(); read_json_str(); }
結果のJSON
{"name":"John Doe","age":43}
JSONの値を不正にしてみる
{"name":"John Doe","age":1000}
注:Personのageはu8
fn main() { // gen_json(); read_json_fs(); read_json_str(); }
結果
error: invalid value: integer `1000`, expected u8 at line 1 column 30 error: invalid value: integer `1000`, expected u8 at line 1 column 29
上記、jsonとstructの例でしたが、例えばHashMapとstructではこうもいかないと思います。 なぜかというと、HashMapはkeyとvalueが静的に決まっている必要があり、nameを取得したらStringだけど、ageを取得したらu8、というような表現力がHashMapにはないからです。(というかそういうことをしたいならstruct)
あるいはHashMapに全部stringで入れて(u8も"20"などのようにStringで入れる)、structと相互変換する、も方法としてはアリかもしれませんが、まあだったらJSONでいいのでは、と思っています。
何を思ってこんなことを書いているかというと、なんらかのデータをデータベースから取得し、一時的にHashMapに入れ、structに変換するのはアリなのか?と思ったのですが、HashMapよりはjsonなどの方が取り回ししやすそうだね、と思った次第です。
無論、データベースから値を取るならそれ用のクレートを使うべきです。(serde_dynamodbなど)