また?
前回のです serde-rs/json にPR投げてmergeされた - KRAZY感情STYLE
今回のPR
Value::pointer とは
pointer を使わずに obj[x][y]
を取ってくる例を考えてみます
use serde_json::{Value, json}; let obj = json!({"x": {"y": 1}}); let value = if let Value::Object(obj) = obj { let x = obj.get("x"); if let Some(Value::Object(child_obj)) = x { child_obj.get("y") } else { None } } else { None }; assert_eq!(value, Some(json!(1)));
こんな感じにわざわざ enum のvariantを剥がす処理を何度も書きます、地獄ですね。Value::pointer を使うと
use serde_json::{Value, json}; let obj = json!({"x": {"y": 1}}); assert_eq!(obj.pointer("/x/y"), Some(json!(1)));
このようにネストしたオブジェクトでもシュッと取ってこれます。前回PRを投げるきっかけになったRFC*1で記述されているpathと同じ記法*2で取ってくることができます。便利。 このメソッドに気づかずに自作しようと思ったのですが、上手く実装できなかったので同様のRFCを実装しているリポジトリ*3 を見たらこのValue::pointerを使っていました、偉い。
Value::pointer の実装を読んだ
自作できなかったのは心に来たので実装を読みました。最初実装に失敗した時は Iterator::fold を使おうとして失敗してたのですがforループで実装されていたので「ア〜〜〜〜」となりました。でもfold でもできそうな気がしたのでやったらできました、高階関数?関数型?に圧倒的感謝! しかし、fold だと /a/b/c/d/e/f/g/h/i
みたいなケースで /a
がなくても /b/c
などを見に行きます、これが1万個のネストしたキーとかだったら辛いですね。 そこでIterator::try_fold
を使うといい感じにearly-returnしてくれるっぽいです。
総括
ドキュメントにこんな乱文よりいい感じの説明があるので読みましょう