はじめに
Rustでは、serdeというクレートを使ってデータのシリアライズ、デシリアライズができるらしいのでやり方を調べてみました。
serdeで対応できるデータフォーマットは、複数ありそれぞれがモジュール化されています。 JSONを使いたい場合は、serde_jsonを追加で読み込んで利用するようです。
準備
適当なプロジェクトを作成して、serde
とserde_json
をプロジェクトに追加します。
$ cargo new serde-json-sample $ cd serde-json-sample $ cargo add serde --features=derive $ cargo add serde_json
Cargo.tomlのdependenciesは以下のような感じになりました。
[dependencies] serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107"
使ってみる
以下のようなJSON文字列をRustから読み込むことを考えます。
[ { "Name": "Alice", "Age": 19 }, { "Name": "Bob", "Age": 18 } ]
試してみる その1(とりあえずパースしてみる)
以下のような、main.rsでひとまず、
が動くことが確認できました。
use serde::{Deserialize, Serialize}; #[allow(non_snake_case)] #[derive(Deserialize, Serialize)] struct Member { Name: String, Age: u8, } fn main() { let json_string = r#" [ { "Name": "Alice", "Age": 19 }, { "Name": "Bob", "Age": 18 } ] "#; let members: Vec<Member> = serde_json::from_str(&json_string).unwrap(); for member in members.iter() { println!("name: {}, age: {}", member.Name, member.Age); } println!("{}", serde_json::to_string(&members).unwrap()); }
ポイント
- JSONの内容をマッピングできるように、
#[derive(Deserialize, Serialize)]
でMember構造体にシリアライザーとデシリアライザーを実装する serde_json::from_str
でJSON文字列を構造体に変換できるserde_json::to_string
で構造体をJSON文字列に変換できる
実行結果は以下。
$ cargo run -q name: Alice, age: 19 name: Bob, age: 18 [{"Name":"Alice","Age":19},{"Name":"Bob","Age":18}]
この方法では、構造体のメンバー名はがJSONのキー名に依存してしまい、#[allow(non_snake_case)]
の指定が必要でした。
試してみる その2(Snake caseとPascal Caseの自動変換をする)
Member構造体に、#[serde(rename_all = "PascalCase")]
を指定すると、JSONのキーをPascalCase、構造体のメンバー名は、snake_caseとして認識してくれました。
修正したコードの差分は以下です。
diff --git a/src/main.rs b/src/main.rs index 7fd87f4..a862c93 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ use serde::{Deserialize, Serialize}; -#[allow(non_snake_case)] #[derive(Deserialize, Serialize)] +#[serde(rename_all = "PascalCase")] struct Member { - Name: String, - Age: u8, + name: String, + age: u8, } fn main() { @@ -24,7 +24,7 @@ fn main() { let members: Vec<Member> = serde_json::from_str(&json_string).unwrap(); for member in members.iter() { - println!("name: {}, age: {}", member.Name, member.Age); + println!("name: {}, age: {}", member.name, member.age); } println!("{}", serde_json::to_string(&members).unwrap());
実行結果は変わらずです。
$ cargo run -q name: Alice, age: 19 name: Bob, age: 18 [{"Name":"Alice","Age":19},{"Name":"Bob","Age":18}]
変換するときにキー名を変更する方法は、他にも色々と用意されているようです。