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

时间:2016-09-02 15:32:20

标签: rust lifetime borrow-checker

此代码:

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 - 这没有多大意义。另外由于我的代码的性质,我无法在循环中创建另一个变量 - 旧的变量必须重用。

2 个答案:

答案 0 :(得分:4)

问题是您错误地使用了as_object。方法的名称(&#34; as&#34;,not&#34; to&#34;或&#34; into&#34;)表示它只是将Json对象表示为另一种类型。 as_object的返回类型为Option<&'a mut Object>,它告诉我们它只返回与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变量,因为它的内容是借用的。如果你真的想这样做,你需要将变量放在一个范围内,以便在循环开始时它不再可用。

答案 1 :(得分:2)

as_object返回对临时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();
    }

}