我正在使用config作为将外部数据加载到程序中的一种方法,该程序在后台使用serde进行反序列化,但是我希望特定字段可以是几种类型之一。 因为我对Rust还是很陌生,所以发现的documentation并没有多大意义。
如何使initial_value
成为几种类型之一:
String
i32
bool
[i32,i32]
我知道我可以使用属性deserialize_with
定向到自定义解码器,但除此之外,我有点茫然。
这是我的代码:
use std::collections::HashMap;
use std::fs;
use config_rs::{Config, ConfigError, File};
#[derive(Debug, Deserialize)]
enum InitialValues {
String,
i32,
bool,
}
#[derive(Debug, Deserialize)]
struct Component {
component: String,
initial_value: InitialValues,
}
#[derive(Debug, Deserialize)]
struct Template {
feature_packs: Vec<String>,
components: Vec<Component>,
}
type Name = String;
type Type = String;
#[derive(Debug, Deserialize)]
pub struct Templates {
templates: HashMap<Name, Template>,
}
impl Templates {
pub fn new(file: &str) -> Result<Self, ConfigError> {
let mut templates = Config::new();
templates.merge(File::with_name(file)).unwrap();
templates.try_into()
}
}
#[derive(Debug)]
pub struct Manager {
pub templates: HashMap<Type, Templates>,
}
impl Manager {
pub fn new(dir: &str) -> Self {
let mut manager = Self {
templates: HashMap::new(),
};
'paths: for raw_path in fs::read_dir(dir).unwrap() {
let path = raw_path.unwrap().path();
let file_path = path.clone();
let type_name = path.clone();
let templates = match Templates::new(type_name.to_str().unwrap()) {
Ok(templates) => templates,
Err(message) => {
println!("TemplateManager: file({:?}), {}", &file_path, message);
continue 'paths;
}
};
manager.templates.insert(
file_path.file_stem().unwrap().to_str().unwrap().to_owned(),
templates,
);
}
manager
}
}
示例配置文件:
---
templates:
orc:
feature_packs:
- physical
- basic_identifiers_mob
components:
- component: char
initial_value: T
goblin:
feature_packs:
- physical
- basic_identifiers_mob
components:
- component: char
initial_value: t
答案 0 :(得分:3)
我将反序列化您提供的示例配置,如下所示。
fetch('http://uinames.com/api/?amount=25®ion=denmark&gender=female')
.then(res => res.json()) // returns response data as JSON object
.then(jsonData => {
const destinationTable = document.querySelector('table'); // select table to which you want to append the data
jsonData.forEach(record => {
const tr = document.createElement('tr'); // create a table row
const tdGender = document.createElement('td'); // create a table cell
tdGender.innerText = record.gender; // insert gender to the created table cell
tr.appendChild(tdGender); // append table cell to the created row
destinationTable.appendChild(tr); // append created row to the table
})
});
答案 1 :(得分:0)
将InitialValues
enum
更改为:
#[derive(Debug, Deserialize)]
#[serde(
rename_all = "lowercase",
untagged
)]
pub enum InitialValue {
Char(char),
String(String),
Int(i32),
Float(f32),
Bool(bool),
Range(Range<i32>)
}
表示以下各项现在有效:
---
example:
feature_packs:
- example
- example
components:
- component: char
initial_value: T
- component: string
initial_value: 'asdasdasd'
- component: int
initial_value: 2
- component: float
initial_value: 3.2
- component: bool
initial_value: true
- component: range
initial_value:
start: 0
end: 9
比我想要的还要冗长,但至少它是可行的。
编辑:感谢@dtolnay的回答,我得以改进此问题,现在它完全按照我的原意读取数据了!
上面的代码已被修改以反映这一点。
此外,通过#[serde(flatten)]
到Templates
就像这样:
#[derive(Debug, Deserialize)]
pub struct Templates {
#[serde(flatten)]
templates: HashMap<Name,Template>,
}
我能够不必在文件开头添加templates:
。