我有包含原语的枚举:
#[deriving(Decodable)]
enum MyValue {
MyString(String),
MyF64(f64),
MyF32(f32),
MyI64(i64),
MyI32(i32),
...
...
}
现在我想将JSON字符串转换为MyValue
的相应变体,例如:
let v: MyValue = parse_json("3.14") // MyF32(3.14f32)
let v: MyValue = parse_json("3.14151515151515") // MyF64(3.14151515151515f64)
let v: MyValue = parse_json("42") // MyI32(42)
let v: MyValue = parse_json("\"hello\"") // MyString("hello")
如果我直接这样做:
let my_value: MyValue = json::decode("3.14").unwrap();
我明白了:
task '<main>' failed at 'called
结果::的unwrap()on an
{ERR {1}}
是否可以仅使用Rust类型系统进行上述操作?
如果没有,应该采取什么方法?我应该使用正则表达式/ PEG解析器还是别的什么?
答案 0 :(得分:4)
我怀疑你能用#[deriving(Decodable)]
做到这一点。这是由rustc --pretty expanded
生成的片段:
__arg_0.read_enum("MyValue", |_d|
_d.read_enum_variant(["MyString", "MyF64", "MyF32", "MyI64", "MyI32"], |_d, i|
::std::result::Ok(match i {
0u => MyString(match _d.read_enum_variant_arg(0u, |_d| ::serialize::Decodable::decode(_d)) {
Ok(__try_var) => __try_var,
Err(__try_var) => return Err(__try_var),
}),
1u => MyF64(match _d.read_enum_variant_arg(0u, |_d| ::serialize::Decodable::decode(_d)) {
Ok(__try_var) => __try_var,
Err(__try_var) => return Err(__try_var),
}),
2u => ...
即,它调度解码器提供的枚举变量索引。事实上,兼容的JSON看起来像这样,你可以see it yourself:
{ "variant": 1, "fields": [12345] } // corresponds to MyF64(12345)
一般来说,我认为无法在任何语言中执行您想要的操作,而不仅仅是在Rust中。例如,JSON不够复杂,无法区分不同类型的整数。另外,Rust Decodable
特征要求您确定使用某种元数据解码的枚举的确切变体;你不能在那里读取任意值并在运行时决定它的类型。所以你需要自己编写一些解析器,但是,我强烈建议你重新考虑你在做什么。 JSON可能不是您需要的语言。