Parse JSON value as Enum in Rust

I have an enumeration that wraps primitives:

#[deriving(Decodable)] enum MyValue { MyString(String), MyF64(f64), MyF32(f32), MyI64(i64), MyI32(i32), ... ... } 

Now I want to convert the JSON string to the corresponding MyValue variant, for example:

 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") 

If I do this directly:

 let my_value: MyValue = json::decode("3.14").unwrap(); 

I get:

task '<main>' failed at 'called Result :: expand () on an Err value: ExpectedError(String or Object, 3.14)'

Is it possible to do the above only with a system like Rust?

If not, what approach should be taken? Should I use regular expressions / PEG parser or something else?

playpen

+2
source share
1 answer

I doubt that you can do this with #[deriving(Decodable)] . Here is a snippet created by 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 => ... 

That is, it sends the index of the enumeration option provided by the decoder. In fact, compatible JSON will look like this: see it yourself :

 { "variant": 1, "fields": [12345] } // corresponds to MyF64(12345) 

In general, I do not see the opportunity to do what you want in any language, and not just in Rust. For example, JSON is not complex enough to distinguish between different types of integers. In addition, the Rust Decodable property requires the definition of the exact decoding option that you decode using some kind of metadata; you cannot read an arbitrary value there and decide its type at runtime. Therefore, you need to write some kind of parser yourself, however I highly recommend reviewing what you are doing. JSON is most likely not the language you need.

+4
source

Source: https://habr.com/ru/post/1234451/


All Articles