JoeZhao

跨出界

Hey, I’m JoeZhao, a software engineer, and a gamer.

RustでJSONを読み込んで解析する

主要なポイントは、Rust が JSON 形式 / ファイルをどのように処理するかについて説明します。

私の要件は次のとおりです:

  1. リモートアドレスから JSON ファイルをダウンロードしてローカルに保存する
  2. この JSON ファイルを読み取る
  3. この JSON ファイルの内容を検索して一致するものを見つける
  4. 検索結果を返す

この記事では、主に 2 番目のステップに焦点を当てます。
まず、次のように JSON 形式を解析する必要があります:

{
    "0100000011D90000": {
        "bannerUrl": "https://img.../37fdb...f83a.jpg",
        "category": [
            "Adventure",
            "RPG"
        ],
        "description": "Welcome to the Sinnoh region! ",
        "developer": null,
        "id": "0100000011D90000",
        "isDemo": false,
        "language": "en",
        "name": "Pok\u00e9mon\u2122 Brilliant Diamond",
        "nsuId": 70010000039950,
        "numberOfPlayers": 1,
        "publisher": "Nintendo",
        "rank": 30712,
        "ratingContent": [
            "Mild Cartoon Violence",
            "Users Interact",
            "In-Game Purchases"
        ],
        "size": 7334789120,
        "version": 0
    },
    ...
}

この処理には、serdeserde_jsonという 2 つのライブラリが必要です。

まず、Cargo.tomlの dependencies にそれぞれ以下を追加します。

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

データモデルの作成 - struct#

Rust がデータ構造を認識できるようにするために、まずstruct Gameのデータモデルを作成して、JSON のレスポンスを模倣します。

Rust では、structを使用してデータモデルを記述します。ここでは、serde の Serialize / Deserialize(シリアライズとデシリアライズを許可する)を派生させるために、ヘッダーでuse serde::{ Deserialize, Serialize }を使用する必要があります。

以下のコードを使用します:

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Game {
    pub banner_url: Option<JsonValue>,
    pub category: Option<Vec<JsonValue>>,
    pub description: Option<JsonValue>,
    pub developer: Option<JsonValue>,
    pub id: Option<JsonValue>,
    pub is_demo: Option<JsonValue>,
    pub language: Option<JsonValue>,
    pub name: Option<JsonValue>,
    pub nsu_id: Option<usize>,
    pub number_of_players: Option<usize>,
    pub publisher: Option<JsonValue>,
    pub rank: Option<JsonValue>,
    pub rating_content: Option<Vec<JsonValue>>,
    pub size: Option<JsonValue>,
    pub version: Option<JsonValue>,
}

PS: Game 構造体内の元の JSON banner_url の命名規則には微妙な違いがあります。前者はキャメルケース(Camel-Case)で、後者はスネークケース(snake_case)です。Rust はデフォルトでスネークケース(snake_case)の命名を好むため、#[serde(rename_all = "camelCase")]を派生させる必要があります。これは、構造体の命名の特徴を記述し、camelCase のすべての内容を蛇形ケースに再命名するためです。

ファイルの読み取り#

以下は、記事の読み取りの簡単な例です。

use std::fs::File;

fn main() {
    // demo.jsonファイルを読み取り、ファイルサイズを出力する
    let demo_file_path = Path::new("appdata/demo.json");
    let file = File::open(demo_file_path)?;
    // ファイルのメタデータを取得する
    let metadata = file.metadata()?;
    println!("The File Size is: {:?} Bytes", metadata.len());
}

ファイルを読み取るには、std::fs::Fileモジュールを使用し、ファイルパスを渡して Open メソッドを使用します。

データの解析#

let content: HashMap<String, Game> = match serde_json::from_reader(&file) {
    Ok(content) => {
        println!("file loaed success");
        content
    },
    Err(e) => {
        println!("file loaed error: {}", e);
        Err(e)?
    }
};

ここでは、serde_json の from_reader メソッドを使用してファイルデータを読み取り、それを Game 構造体の形式に解析しています。JSON の構造にエラーがある場合、プログラムは終了し、エラーが発生します。

ちなみに、HashMap の値を読み取る場合は、get メソッドを使用できます。例えば:

println!("{:?}", content.unwrap().get("0100000000010000").unwrap().name);

お読みいただきありがとうございます。

この記事のソースコードはこちらで確認できます。

--EOF--

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。