rustc_serialize::Json while循环中借用的值不够活

rustc_serialize::Json value borrowed in a while loop does not live enough

此代码:

extern crate rustc_serialize;

use rustc_serialize::json;
use rustc_serialize::json::Json;

fn main() {
    let mut string: String = "{\"num\": 0}".to_string();

    let mut obj = Json::from_str(&string).unwrap().as_object().unwrap();

    let mut num = obj.get("num").unwrap().as_u64().unwrap();

    for i in 1..10 {
        println!("{:?}", num);
        string = format!("{}{}{}", "{\"num\": ", i, "}");
        obj = Json::from_str(&string).unwrap().as_object().unwrap();
        num = obj.get("num").unwrap().as_u64().unwrap();
    }
}

产生错误

error: borrowed value does not live long enough
 --> src/main.rs:9:19
  |>
9 |>     let mut obj = Json::from_str(&string).unwrap().as_object().unwrap();
  |>                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not live long enough
note: reference must be valid for the block suffix following statement 1 at 9:72...
 --> src/main.rs:9:73
  |>
9 |>     let mut obj = Json::from_str(&string).unwrap().as_object().unwrap();
  |>                                                                         ^
note: ...but borrowed value is only valid for the statement at 9:4
 --> src/main.rs:9:5
  |>
9 |>     let mut obj = Json::from_str(&string).unwrap().as_object().unwrap();
  |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
 --> src/main.rs:9:5
  |>
9 |>     let mut obj = Json::from_str(&string).unwrap().as_object().unwrap();
  |>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: borrowed value does not live long enough
  --> src/main.rs:16:15
   |>
16 |>         obj = Json::from_str(&string).unwrap().as_object().unwrap();
   |>               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not live long enough
note: reference must be valid for the block suffix following statement 1 at 9:72...
 --> src/main.rs:9:73
  |>
9 |>     let mut obj = Json::from_str(&string).unwrap().as_object().unwrap();
  |>                                                                         ^
note: ...but borrowed value is only valid for the statement at 16:8
  --> src/main.rs:16:9
   |>
16 |>         obj = Json::from_str(&string).unwrap().as_object().unwrap();
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider using a `let` binding to increase its lifetime
  --> src/main.rs:16:9
   |>
16 |>         obj = Json::from_str(&string).unwrap().as_object().unwrap();
   |>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我不明白这是什么问题,错误是误导性的还是什么?为什么它指向 Json - 这没有多大意义。此外,由于我的代码的性质,我无法在循环内创建另一个变量 - 必须重用旧变量。

问题是您使用 as_object 不正确。该方法的名称("as",而不是 "to" 或 "into")表示它只是将 Json 对象表示为另一种类型。 as_object 的 Return 类型是 Option<&'a mut Object>,这告诉我们它只是 returns 一个与 Json 对象本身一样长的引用。当你在一行中使用它时,借用检查器不高兴,因为中间 Json 对象将在这一行之后被删除,但你尝试使用保留的引用。

一个解决方案是将 Json 存储在变量中,根本不存储引用:

fn main() {

    let mut string: String = "{\"num\": 0}".to_string();

    let mut json = Json::from_str(&string).unwrap();
    let mut num = json.as_object().unwrap().get("num").unwrap().as_u64().unwrap();

    for i in 1..10 {
        println!("{:?}", num);
        string = format!("{}{}{}", "{\"num\": ", i, "}");
        json = Json::from_str(&string).unwrap();
        num = json.as_object().unwrap().get("num").unwrap().as_u64().unwrap();
    }

}

如果您将 as_object 的结果存储在一个变量中,Rust 不会让您重新分配 json 变量,因为它的内容是借用的。如果你真的想这样做,你需要把变量放在一个范围内,这样它在循环开始时就不再可用了。

as_object returns 对临时 JSON 对象的内部映射的引用。由于 JSON 对象是临时的,内部映射也是。 不过,您可以轻松打开地图:

extern crate rustc_serialize;

use rustc_serialize::json;
use rustc_serialize::json::{Json, Object};

fn main() {
    // while the online documentation of Json has a `into_object` method,
    // the local nightly rustc I have does not have it anymore
    fn into_object(json: Json) -> Option<Object> {
        if let Json::Object(map) = json {
            Some(map)
        } else {
            None
        }
    }

    let mut string: String = "{\"num\": 0}".to_string();

    let mut obj = into_object(Json::from_str(&string).unwrap()).unwrap();

    let mut num = obj.get("num").unwrap().as_u64().unwrap();

    for i in 1..10 {
        println!("{:?}", num);
        string = format!("{}{}{}", "{\"num\": ", i, "}");
        obj = into_object(Json::from_str(&string).unwrap()).unwrap();
        num = obj.get("num").unwrap().as_u64().unwrap();
    }

}