🌊
RustでJSONをファイルに書いたり読んだりする
いやあの、Rustを勉強中でして、serde
を使ってStruct
とHashMap
が絡むようなやつをJSONにしてファイルに書いたり読んだりするのがやりたかっただけなのですが、意外と時間かかったのでメモっときます。
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::io::BufReader;
#[derive(Serialize, Deserialize, Debug)]
struct Memo {
id: isize,
body: String,
star: bool,
}
type Memos = HashMap<String, Memo>;
fn main() {
write_file("hello".to_string());
read_file();
}
fn write_file(body: String) -> std::io::Result<()> {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open("memo.json")?;
println!("file: {:#?}", file);
let memo = Memo {
id: 100,
body: body,
star: true,
};
let mut memos = HashMap::new();
memos.insert(memo.id.to_string(), memo);
let memos_text = serde_json::to_string(&memos).unwrap();
println!("memos: {}", &memos_text);
write!(&file, "{}", memos_text)?;
Ok(())
}
fn read_file() -> std::io::Result<()> {
let mut memos_file = OpenOptions::new()
.read(true)
.write(true)
.open("memo.json")?;
let reader = BufReader::new(memos_file);
let memos: Memos = serde_json::from_reader(reader)?;
println!("memo_text: {:?}", memos);
Ok(())
}
どこでハマったかというと、JSONとかSerdeとかいうよりは、ファイルに書き込むところのwrite!(&file, "{}", memos_text)
です。ファイルに書き込んだJSONの"
がどうやっても\
でエスケープされてしまって、テキストになるんで、次に読み込む時にdeserialize
しにくいという内容
serde_json::to_writer(&file, &memos_text)?;
// => "{\"100\":{\"id\":100,\"body\":\"hello\",\"star\":true}}"
write!(&file, "{:?}", memos_text)?;
// => "{\"100\":{\"id\":100,\"body\":\"hello\",\"star\":true}}"
write!(&file, "{}", memos_text)?;
// => {"100":{"id":100,"body":"hello","star":true}} やった!
最後の行に行き着くまでにそこそこ時間が溶けました。{:?}
って単なるフォーマッターかと思ってたけどエスケープとかしてくるのか、っていうだけのお話し。
Discussion