LoginSignup
5
2

More than 1 year has passed since last update.

[Rust]JSON APIでデータにフィールドがなくてもエラー回避がしたい!

Posted at

3回同じことを調べてしまったので結論だけ先に書いておく。

毎回、skip_deserialize_if とか ignore とかで探してしまうが、これをつけるだけ。

 #[serde(default)]

#[derive(Deserialize)] なstructでも #[serde(skip_if_empty)] がしたい!

JSONなAPIでパラメータを受け取るとき、全てのkeyがないとdeserializeの時にエラーになる。
こう言う構造体があって

use serde::{Deserialize, ...};

#[derive(Deserialize)]
pub struct HogeRequest {
    pub id: i32,
    pub name: String, // <- 必須
    pub memo: String, // <- なくても良い
}

memoが入っていないとエラーになる。

$ curl -X POST https://example.com/api/hoge -d '{
  "id": 1,
  "name": "これは必須"
}'

# エラーレスポンス memoというフィールドがないと言われる
> [ERROR] missing field 'memo' at line 1 column xxx

対処法としては3つ

  1. "memo": "", のように必ずフィールドを設定する
    1. react-formだと空白のフィールドを指定してくれない。なので却下
  2. Optionにする。
    1. 今回はnullと空文字を分ける必要がない。DBも含めて面倒。却下
  3. serdeのオプションやエラー回避処理を使う

なので、フィールドがなくてもエラーにせずに空文字が入るようにしたい。
例えばgoだと omitempty 入れれば良いだけ。

type HogeRequest struct {
  ID int `json:"name"`
  Name string `json:"name"`
  Memo string `json:"memo,omitempty"` // フィールドがない場合は空文字が入る
}

で、シリアライズ時のものとしてskip_serialize_if=is_empty というのがあるので
skip_deserialize_ifみたいなものがあるかと思って探してしまうがそんなものはない。
ignore というオプションもありそうだが存在しない。
正解はdefaultを使うオプション

use serde::{Deserialize, ...};

#[derive(Deserialize)]
pub struct HogeRequest {
    pub id: i32,
    pub name: String, // <- 必須
    #[serde(default)]
    pub memo: String, // <- ないと空文字が入る
}

default traitを実装してやることで、Vec<String> とか HashSet<String>とかでもよしなにやってくれる。

5
2
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
5
2