🐻
RustでJSONを扱う(serde_json) JSONの編集
サンプル
serde_json::Value
を編集する
これまでの記事では serde_json
を使ったJSONの読み込みについて述べてきたが、JSONを編集したくなっても来るだろう。
serde_json::Value
でパースされたJSONを編集していく。
下記のようにJSONを読み込んでおく。
let json = from_reader::<BufReader<File>, Value>(reader);
let mut json: Value = match json {
Ok(o) => o,
Err(e) => {
println!("Failed to parse json.");
return Err(Box::new(e));
}
};
// 変数 "json" に読み込まれたJSON
//{
// "live_music_club": "STARRY",
// "o-ne-chan": {
// "name": "Seika",
// "age": 29
// },
// "band": [
// {
// "band_name": "Kessoku Band",
// "member": [
// {
// "name": "Nijika",
// "age": 17
// },
// {
// "name": "Ryo",
// "age": 16
// },
// {
// "name": "Goto",
// "age": 15
// },
// {
// "name": "Ikuyo",
// "age": 16
// }
// ]
// }
// ]
//}
get_mut()
で書き換える
mutableな参照を取得
let target_member: &Value = &json["band"][0]["member"][3];
if target_member.is_null() {
return Err("Failed to get member".into());
}
let target_name: Option<&mut Value> = json["band"][0]["member"][3].get_mut("name");
let target_name: &mut Value = match target_name {
Some(s) => s,
None => {
return Err("Failed to get name".into());
}
};
ここで "json["band"][0]["member"]" は "{"name": "Ikuyo", "age": 16 }" のことであるが、もし存在しない場合 serde_json::Value::Null
に get_mut()
しようとしてpanicを起こす。
そのためあらかじめ is_null()
な場合を弾いた。
代入
上で取得した "json["band"][0]["member"][3]["name"]" にderefし、serde_json::Value
を代入する。
let new_name: String = String::from("Kita");
println!("\"Kita-ikuyo-tte-ahoka-i\"");
println!("Fix : {} -> {}", target_name, new_name);
*target_name = Value::String(new_name);
出力結果
サンプルを実行すると下記のようになる。
{"band":[{"band_name":"Kessoku Band","member":[{"age":17,"name":"Nijika"},{"age":16,"name":"Ryo"},{"age":15,"name":"Goto"},{"age":16,"name":"Ikuyo"}]}],"live_music_club":"STARRY","o-ne-chan":{"age":29,"name":"Seika"}}
"Kita-ikuyo-tte-ahoka-i"
Fix : "Ikuyo" -> Kita
{"band":[{"band_name":"Kessoku Band","member":[{"age":17,"name":"Nijika"},{"age":16,"name":"Ryo"},{"age":15,"name":"Goto"},{"age":16,"name":"Kita"}]}],"live_music_club":"STARRY","o-ne-chan":{"age":29,"name":"Seika"}}
バンドメンバーの4人目の名前が "Ikuyo" から "Kita" に変更されているはずである。
[] (square brackets) で書き換える
こちらのほうが直感的でわかりやすいかもしれない。
let new_name_2: String = String::from("Hitori");
println!("\"Goto sa...\"");
println!("Fix : {} -> {}", json["band"][0]["member"][2]["name"], new_name_2);
json["band"][0]["member"][2]["name"] = Value::String(new_name_2);
しかし存在しないキーならば単純に追記されるが、"json["band"][0]["member"][100]" などに追記しようとするとpanicを起こすため、 get_mut()
のほうが安全に扱えるだろう。
新しい値を挿入する
バンドメンバーの楽器を追記したい。
let instrument = "Guiter".to_string();
json["band"][0]["member"][2]["instrument"] = Value::String(instrument.clone());
let target_member: Option<&mut serde_json::Map<String, Value>> = json["band"][0]["member"][3].as_object_mut();
if let Some(s) = target_member {
s.insert(String::from("instrument"), instrument.clone().into());
}
1つ目は前述の存在しない場合のキーは新規で作られるので直接代入してしまうことができる。
2つ目は代入するためのmutableなobjectを as_object_mut()
で取得してそこに insert()
で挿入している。
Discussion