Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

RustでデータをJSONやYAML等にserialize/deserializeする方法

この記事はWanoアドベントカレンダーの4日目の記事です。

TL;DR

  • 使うcrate
  • serdeはserialize/deserializeの為の仕組みを提供する
  • serde_json等の各フォーマット毎のserdeに対応したcrateを使って具体的なフォーマットとの変換を行う

Rustでserialize/deserializeを行うには

serdeserde_deriveというcrateを使います。
この2つのcrateを使ってSerialize/Deserialize traitを構造体などに実装する事でserializeが出来るようになります。
serde_deriveが自動実装のマクロを提供しているので、ユーザーは構造体等の定義の上に#[derive(Serialize, Deserialize)]と書くだけでOKです。

JSONとのserialize/deserializeを実装してみる

serialize

まずはJSONへのserializeを実装してみましょう。
$ cargo new serde_exampleという感じでプロジェクトを作ります。
できましたら今作ったプロジェクトのディレクトリに移動して($ cd serde_example)、Cargo.tomlを開いて[dependencies]の下に次の3行を追加します。

serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

次にsrc/main.rsを開いて次の様に編集します。

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

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

fn main() -> Result<(), Box<std::error::Error>> {
    let tarou = Person { name: "太郎".to_string(), age: 18 };
    let json = serde_json::to_string(&tarou)?;
    println!("{}", json);

    Ok(())
}

$ cargo runで実行します。

必要なcrateをダウンロードしたりコンパイルしたり等のメッセージが色々出てると思いますが、最後に次のテキストが表示されていれば成功です。

{"name":"太郎","age":18}

これでJSONへのシリアライズが出来ました。

ユーザーは構造体等の上に#[derive(Serialize, Deserialize)]と書き(必要に応じて他のtrait等も一緒に書く)、SerializeDeserializeを実装します。
実装したらserdeに対応している目的のフォーマット用のcrateで実際に変換します。
ここではserde_jsonがこれに当たり、serde_json::to_string(&tarou)とすることで構造体からJSONへと変換しています。

deserialize

次にJSONからのdeserializeを実装してみましょう。
上で編集したmain.rsmain関数を次の様に変更します。

fn main() -> Result<(), Box<std::error::Error>> {
    let tarou = Person { name: "太郎".to_string(), age: 18 };
    let json = serde_json::to_string(&tarou)?;
    println!("{}", json);

    // ここが追加分
    let json = r#"{ "name": "花子", "age": 68 }"#;
    let hanako: Person = serde_json::from_str(json)?;
    println!("{:?}", hanako);

    Ok(())
}

$ cargo runで実行します。

{"name":"太郎","age":18}
Person { name: "花子", age: 68 }

Person {~}の行が増えました。JSON文字列から構造体に正しく変換できています。

serdeに対応したcrate

serdeに対応しているcrateには次の様な物があります。

Format crate github
JSON serde_json https://github.com/serde-rs/json
YAML serde_yaml https://github.com/dtolnay/serde-yaml
MessagePack rmp, rmp-serialize, rmps, rmpv https://github.com/3Hren/msgpack-rust
TOML toml https://github.com/alexcrichton/toml-rs
x-www-form-urlencoded serde_urlencoded https://github.com/nox/serde_urlencoded

serdeのドキュメントにその他の形式のcrateの紹介もあります。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
9
Help us understand the problem. What are the problem?