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つ
-
"memo": "",
のように必ずフィールドを設定する- react-formだと空白のフィールドを指定してくれない。なので却下
- Optionにする。
- 今回はnullと空文字を分ける必要がない。DBも含めて面倒。却下
- 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>とかでもよしなにやってくれる。