1
0

Rust: 構造体 in 構造体 を JSON/YAML パース時に扱う

Last updated at Posted at 2023-09-09

はじめに

意外と構造体 in 構造体を JSON/YAML パースとセットで扱っている記事がぱっと出てこなかったのでメモ。

パッケージの導入

例によって、 serde を使う。
また、JSON -> serde_json、 YAML -> serde_yaml を使う。

cargo add serde --features="derive"
cargo add serde_json
cargo add serde_yaml

構造体の定義

構造体 in 構造体を作って、JSON/YAML 等からデシリアライズ・シリアライズを行う場合、すべての構造体に対して親の構造体に同じ derive 属性を付ける
これがないと、エラーを起こす。
逆に、子側で属性が増えるのは問題ない

main.rs
#[derive(Serialize, Deserialize, Debug)]
struct Person {
    firstname: String,
    sirname: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Book {
    people: Vec<Person>,
}

エラー例

例えば、Book 側(ここでは親側)のみ derive を付けて、Person 側には付けない状態でコンパイルしようとすると、以下のようなエラーが出力される。

error[E0277]: the trait bound `Person: Serialize` is not satisfied

error[E0277]: the trait bound `Person: Deserialize<'_>` is not satisfied

error[E0277]: `Person` doesn't implement `Debug`

実行部分の実装

main.rs
use serde::{Deserialize, Serialize};

use std::fs::File;
use std::io::BufReader;

// ここに上記構造体定義

fn main() {
    let file_name = "data/sample.json";

    let file = File::open(file_name).unwrap();
    let reader = BufReader::new(file);

    // JSON の場合
    let data: Book = serde_json::from_reader(reader).unwrap();

    // YAML の場合
    let data: Book = serde_yaml::from_reader(reader).unwrap();

    println!("{:?}", data);

    for person in data.people.iter() {
        println!("{} {}", person.firstname, person.sirname);
    }
}

まとめ

JSON/YAML 等で構造体を複合的に扱う場合、すべてに属性つけるのを忘れずに~~

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0