📍

[Tauri v2.0]JSON データをRust BackendからFrontendに送信する方法

2024/12/22に公開

1.Tauriとは
Tauriは、Rust製のクロスプラットフォーム対応デスクトップアプリケーションフレームワークです。
Electronなどと同様にHTML/CSS/JavaScriptでフロントエンドを開発しつつ、バックエンドロジックをRustで記述できるのが特徴です。
IPC (Inter-Process Communication) を利用して、Rust(バックエンド)とJavaScript(フロントエンド)間でデータのやり取りを行うため、高速かつセキュアなアプリケーションを構築できます。
2.実行環境
今回使用する環境は以下のとおりです。

Rust バージョン: rustc 1.83.0

[build-dependencies]
tauri-build = { version = "2.0.0-rc.13", features = [] }

[dependencies]
tauri = { version = "2.1.1", features = [] }
tauri-plugin-shell = "2.1.1"
serde = "1.0.216"
serde_json = "1"

Tauri のバージョンは 2.1.1 系を使用しています。

3.基本実装
3-1. 目的
最もシンプルなパターンとして、Rust 側(バックエンド)で定義した構造体を JSON としてフロントエンドに返す方法を紹介します。
Tauri には JSON シリアライズの仕組みが備わっているため、serde::Serialize を実装した構造体をコマンドの返り値にすれば、そのまま JSON データとしてフロントエンドに送信できます。

3-2. コード例
以下は Rust 側(src-tauri/src/main.rs など)に記述する例です。

use serde::Serialize;
#[derive(Serialize)]
struct Person {
    id: i32,
    name: String,
}

#[tauri::command]
fn send_json() -> Person {
    Person {
        id: 1,
        name: "Alice".to_string(),
    }
}

戻り値として Person 構造体を返すだけで、Tauri 側が JSON 変換を行い、フロントエンドに送ってくれます。
3-3. フロントエンドの受け取り例
フロントエンド(JavaScript/TypeScript)では、下記のように invoke を使って呼び出します。

import { invoke } from '@tauri-apps/api/tauri';

async function fetchData() {
  try {
    const person = await invoke('send_json');
    // person は { id: number, name: string } として取得
    console.log('Received:', person);
  } catch (error) {
    console.error('Error:', error);
  }
}

4.応用: カスタムエラー(MyError)とIpcResponseの使用
上記のように返却する構造体が単純な場合は、#[tauri::command] で返すだけで十分です。
しかし、カスタムエラーを返したいときなど、IpcResponseで明示的に制御したい場合があります。
以下に、その実装例を示します。
4-1. カスタムエラー MyError の定義例

#[derive(Debug)]
struct MyError;

// Displayトレイトの実装
impl std::fmt::Display for MyError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "An error occurred while sending JSON data.")
    }
}

// Errorトレイトの実装
impl std::error::Error for MyError {}

MyErrorを自作し、Debug, Display, std::error::Error の各トレイトを実装して、Rust のエラー型として扱えるようにした例です。

use tauri::ipc::{InvokeResponseBody, IpcResponse};
// コマンド定義
#[tauri::command]
fn send_json() -> Result<InvokeResponseBody, MyError> {
    // JSONデータの作成
    let result = Person {
        id: 1,
        name: "Alice".to_string(),
    };

    // IpcResponseを使用してレスポンスを作成
    let response = IpcResponse::body(result).unwrap();

    // 成功時にOkでラップして返す
    Ok(response)
}

IpcResponse::body(result) を呼び出すと、result(ここでは Person)を JSONとしてシリアライズしたレスポンスボディ(InvokeResponseBody)を返せます。

将来的に何らかの条件でエラーを返す場合、Err(MyError) を返すなどして、フロントエンド側の catch ブロックで処理できます。

import { invoke } from '@tauri-apps/api/tauri';

async function fetchDataIpc() {
  try {
    const response = await invoke('send_json');
    console.log('Received:', response); 
    // response は { id: number, name: string } に相当
  } catch (error) {
    console.error('Error:', error);
    // MyError が発生した場合もここで捕捉
  }
}

  1. まとめ
    TauriはBackend側から簡単にJSONデータを送信することができます。本記事で実装に役立てば幸いです。

Discussion