2020-03-01(Sun) 書き直し
次のような JSONファイル を読み込みたいとしよう。
linear-regression-wars.json:
{
"fightingNations": [
{
"name": "Kifuwara-kingdom-1",
"win": 1230,
"draw": 0,
"lose": 770,
"tanks": {
"tako2000": {
"number": 50,
"magazine": "grape5x3-hole3"
},
"tako3000": {
"number": 200,
"magazine": "grape2x4-hole1"
},
"tako5000": {
"number": 20,
"magazine": "grape5x3-hole3"
}
}
},
{
"name": "Oton-kingdom-1",
"win": 770,
"draw": 0,
"lose": 1230,
"tanks": {
"tako2000": {
"number": 50,
"magazine": "grape5x3-hole3"
},
"tako3000": {
"number": 200,
"magazine": "grape2x4-hole1"
},
"tako5000": {
"number": 20,
"magazine": "grape5x3-hole3"
}
}
}
]
}
Cargo.toml
には例えば次のように書いてくれだぜ。
[dependencies]
serde = { version = "^1.0.101", features = ["derive"] }
serde_json = "^1.0.41"
main.rs
は次のように書いてくれだぜ。
//!
//! [[Rust] Serdeのシリアライズ/デシリアライズを試してみる](https://dev.classmethod.jp/server-side/language/rust-serde-getting-started/)
//! [Rust】serde_jsonの使い方](https://www.amusement-creators.info/post/articles/advent_calendar/2019/02_0/)
//! [Serialize fields as camelCase](https://serde.rs/attr-rename.html)
//!
extern crate serde;
extern crate serde_json;
use serde::Deserialize;
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
#[serde(rename_all = "camelCase")]
#[derive(Deserialize, Debug)]
struct LinearRegressionWars {
fighting_nations: Vec<FightingNation>,
}
#[derive(Deserialize, Debug)]
struct FightingNation {
name: String,
win: u32,
draw: u32,
lose: u32,
tanks: HashMap<String, Tank>,
}
#[derive(Deserialize, Debug)]
struct Tank {
number: u16,
magazine: String,
}
fn main() {
// Open file.
let mut file = match File::open("./linear-regression-wars.json") {
Ok(n) => n,
Err(err) => panic!("File open error. {:?}", err),
};
// Read file.
let mut contents = String::new();
match file.read_to_string(&mut contents) {
Ok(n) => n,
Err(err) => panic!("File open error. {:?}", err),
};
// Desirialize.
let linear_regression_wars = match serde_json::from_str::<LinearRegressionWars>(&contents) {
Ok(n) => n,
Err(err) => panic!("File open error. {:?}", err),
};
for fighting_nation in linear_regression_wars.fighting_nations {
println!("name={}", fighting_nation.name);
println!(
" tank number={}",
fighting_nation.tank["tako2000"].number
);
}
println!("Info | Finished.");
}
Output:
name=Kifuwara-kingdom-1
tank number=50
name=Oton-kingdom-1
tank number=50
Info | Finished.
とりあえず こんな感じ。
ここから下は古い記事
新しい方法も追いかけてないし、古い方法でも真似する。
Cargo.toml
[dependencies]
serde = "1.0"
serde_json = "1.0"
とりあえず シリアライズ、デシリアライズの略という serde
クレートを使う。
たまには
cargo update
でもしろだぜ。
とりあえず 読み書きしたい JSON を用意しろだぜ☆
わたしは コンピューター囲碁で使ったことがある JSON を用意する。
config.json
{
"comment": "AI竜星戦2018用設定ファイル",
"boardSize": 19,
"boardInit": [
"+++++++++++++++++++",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+ +",
"+++++++++++++++++++"
],
"sente": "black",
"rule": "jungo",
"komiJungo": 6.5,
"outFile": "C:/MuzudhoDrive/projects_cpp/cgfgoban109_for_kifuwarabe2018_ローカルテスト環境/out.txt",
"inFile": "C:/MuzudhoDrive/projects_cpp/cgfgoban109_for_kifuwarabe2018_ローカルテスト環境/in.txt"
}
これを読み込んで オブジェクトに一発で入れたいわけだぜ。
config_file.rs
/// 設定ファイル
/// 参考: https://github.com/serde-rs/json |シリアライズ、デシリアライズ。
extern crate serde_json;
use serde_json::Value;
use std::fs::File;
use std::io::Read;
pub struct Config {
/// コメント。
pub comment: String,
/// 何路盤。
pub board_size: usize,
/// 大会用 out.txt 局面ファイルへのパス。
pub out_path: String,
/// 大会用 in.txt 局面ファイルへのパス。
pub in_path: String,
}
impl Config {
pub fn load(path:&str) -> Config {
let mut file = match File::open(path) {
Ok(n) => n,
Err(err) => panic!("File open error. {:?}", err),
};
let mut contents = String::new();
match file.read_to_string(&mut contents) {
Ok(n) => n,
Err(err) => panic!("File open error. {:?}", err),
};
// https://docs.serde.rs/serde_json/value/enum.Value.html
let document: Value = match serde_json::from_str(&contents) {
Ok(n) => n,
Err(err) => panic!("File open error. {:?}", err),
};
Config {
comment: match document["comment"].as_str() {
Some(n) => n.to_string(),
None => "".to_string(),
},
board_size: match document["boardSize"].as_i64() {
Some(n) => n as usize, // FIXME 変換方法が分からん☆(^~^)as使う☆(^~^)
None => 19usize,
},
out_path: match document["outFile"].as_str() {
Some(n) => n.to_string(),
None => "".to_string(),
},
in_path: match document["inFile"].as_str() {
Some(n) => n.to_string(),
None => "".to_string(),
},
}
}
}
よく分からんので こんな感じに書いている。
こんなんでいいのか、さっぱり分からん。