无法使用 Rustc-serialize 处理 JSON 中的可选字段
Unable to tackle optional fields in JSON with Rustc-serialize
我正在尝试使用 rustc_serialize 将 JSON 反序列化为 Rust 结构。问题是某些 JSONs 有一些可选字段,即可能存在也可能不存在。遇到第一个不存在的字段时,解码器似乎会退出并且不考虑后续字段,即使它们存在也是如此。有办法克服这个问题吗?
代码如下:
extern crate rustc_serialize;
#[derive(Debug)]
struct B {
some_field_0: Option<u64>,
some_field_1: Option<String>,
}
impl rustc_serialize::Decodable for B {
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
Ok(B {
some_field_0: d.read_struct_field("some_field_0", 0, |d| rustc_serialize::Decodable::decode(d)).ok(),
some_field_1: d.read_struct_field("some_field_1", 0, |d| rustc_serialize::Decodable::decode(d)).ok(),
})
}
}
fn main() {
{
println!("--------------------------------\n1st run - all field present\n--------------------------------");
let json_str = "{\"some_field_0\": 1234, \"some_field_1\": \"There\"}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
{
println!("\n\n--------------------------------\n2nd run - \"some_field_1\" absent\n---------------------------------");
let json_str = "{\"some_field_0\": 1234}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
{
println!("\n\n--------------------------------\n3rd run - \"some_field_0\" absent\n---------------------------------");
let json_str = "{\"some_field_1\": \"There\"}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
}
这是输出:
--------------------------------
1st run - all field present
--------------------------------
JSON: {"some_field_0": 1234, "some_field_1": "There"}
Decoded: B { some_field_0: Some(1234), some_field_1: Some("There") }
--------------------------------
2nd run - "some_field_1" absent
---------------------------------
JSON: {"some_field_0": 1234}
Decoded: B { some_field_0: Some(1234), some_field_1: None }
--------------------------------
3rd run - "some_field_0" absent
---------------------------------
JSON: {"some_field_1": "There"}
Decoded: B { some_field_0: None, some_field_1: None }
请注意,第三个 运行 产生了意外的结果。当解码器无法找到 some_field_0
时,它会在所有后续标记上失败,即使存在 some_field_1
。
您的 Decodable
实施有问题。使用自动生成的实现有效:
#[derive(Debug, RustcDecodable)]
struct B {
some_field_1: Option<String>,
some_field_0: Option<u64>,
}
JSON: {"some_field_1": "There"}
Decoded: B { some_field_1: Some("There"), some_field_0: None }
如果可以,使用生成的实现是正确的做法。如果你不能,这里是正确的实现:
impl rustc_serialize::Decodable for B {
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
Ok(B {
some_field_0: try!(d.read_struct_field("some_field_0", 0, |d| rustc_serialize::Decodable::decode(d))),
some_field_1: try!(d.read_struct_field("some_field_1", 0, |d| rustc_serialize::Decodable::decode(d))),
})
}
}
重要的变化是 try!
的使用。解码可能会失败。通过使用 ok
,您是说解码失败实际上是 成功 ,尽管 None
.
的解码成功
我正在尝试使用 rustc_serialize 将 JSON 反序列化为 Rust 结构。问题是某些 JSONs 有一些可选字段,即可能存在也可能不存在。遇到第一个不存在的字段时,解码器似乎会退出并且不考虑后续字段,即使它们存在也是如此。有办法克服这个问题吗?
代码如下:
extern crate rustc_serialize;
#[derive(Debug)]
struct B {
some_field_0: Option<u64>,
some_field_1: Option<String>,
}
impl rustc_serialize::Decodable for B {
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
Ok(B {
some_field_0: d.read_struct_field("some_field_0", 0, |d| rustc_serialize::Decodable::decode(d)).ok(),
some_field_1: d.read_struct_field("some_field_1", 0, |d| rustc_serialize::Decodable::decode(d)).ok(),
})
}
}
fn main() {
{
println!("--------------------------------\n1st run - all field present\n--------------------------------");
let json_str = "{\"some_field_0\": 1234, \"some_field_1\": \"There\"}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
{
println!("\n\n--------------------------------\n2nd run - \"some_field_1\" absent\n---------------------------------");
let json_str = "{\"some_field_0\": 1234}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
{
println!("\n\n--------------------------------\n3rd run - \"some_field_0\" absent\n---------------------------------");
let json_str = "{\"some_field_1\": \"There\"}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
}
这是输出:
--------------------------------
1st run - all field present
--------------------------------
JSON: {"some_field_0": 1234, "some_field_1": "There"}
Decoded: B { some_field_0: Some(1234), some_field_1: Some("There") }
--------------------------------
2nd run - "some_field_1" absent
---------------------------------
JSON: {"some_field_0": 1234}
Decoded: B { some_field_0: Some(1234), some_field_1: None }
--------------------------------
3rd run - "some_field_0" absent
---------------------------------
JSON: {"some_field_1": "There"}
Decoded: B { some_field_0: None, some_field_1: None }
请注意,第三个 运行 产生了意外的结果。当解码器无法找到 some_field_0
时,它会在所有后续标记上失败,即使存在 some_field_1
。
您的 Decodable
实施有问题。使用自动生成的实现有效:
#[derive(Debug, RustcDecodable)]
struct B {
some_field_1: Option<String>,
some_field_0: Option<u64>,
}
JSON: {"some_field_1": "There"}
Decoded: B { some_field_1: Some("There"), some_field_0: None }
如果可以,使用生成的实现是正确的做法。如果你不能,这里是正确的实现:
impl rustc_serialize::Decodable for B {
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
Ok(B {
some_field_0: try!(d.read_struct_field("some_field_0", 0, |d| rustc_serialize::Decodable::decode(d))),
some_field_1: try!(d.read_struct_field("some_field_1", 0, |d| rustc_serialize::Decodable::decode(d))),
})
}
}
重要的变化是 try!
的使用。解码可能会失败。通过使用 ok
,您是说解码失败实际上是 成功 ,尽管 None
.