我正在尝试围绕serde_json和amp;写一个包装器。 Rocket的FromData
强烈键入我与服务器交换的一些JSON。
我无法编译以下代码:
extern crate serde_json;
extern crate rocket;
extern crate serde;
use serde::ser::Error;
use serde_json::Value;
use rocket::data::DataStream;
use rocket::outcome::IntoOutcome;
use std::io::Read;
static NULL: Value = serde_json::Value::Null;
pub struct ResponseJSON<'v> {
success: bool,
http_code: u16,
data: &'v serde_json::Value,
}
impl<'v> ResponseJSON<'v> {
pub fn ok() -> ResponseJSON<'v> {
ResponseJSON {
success: true,
http_code: 200,
data: &NULL,
}
}
pub fn http_code(mut self, code: u16) -> ResponseJSON<'v> {
self.http_code = code;
self
}
pub fn data(mut self, ref_data: &'v serde_json::Value) -> ResponseJSON<'v> {
self.data = ref_data;
self
}
pub fn from_serde_value(json: &'v serde_json::Value) -> ResponseJSON<'v> {
if !json["success"].is_null() {
ResponseJSON::ok()
.http_code(json["http_code"].as_u64().unwrap() as u16)
.data(json.get("data").unwrap_or(&NULL))
} else {
ResponseJSON::ok()
.data(json.pointer("").unwrap())
}
}
}
impl<'v> rocket::data::FromData for ResponseJSON<'v> {
type Error = serde_json::Error;
fn from_data(request: &rocket::Request, data: rocket::Data) -> rocket::data::Outcome<Self, serde_json::Error> {
if !request.content_type().map_or(false, |ct| ct.is_json()) {
println!("Content-Type is not JSON.");
return rocket::Outcome::Forward(data);
}
let data_from_reader = data.open().take(1<<20);
let value = serde_json::from_reader(data_from_reader);
let unwraped_value : Value = if value.is_ok() { value.unwrap() } else { Value::Null };
if !unwraped_value.is_null() {
Ok(ResponseJSON::from_serde_value(&unwraped_value)).into_outcome()
} else {
Err(serde_json::Error::custom("Unable to create JSON from reader")).into_outcome()
}
}
}
fn main() {
println!("it runs!");
}
编译器的错误:
Compiling tests v0.1.0 (file:///Users/bgbahoue/Projects.nosync/tests)
error: `unwraped_value` does not live long enough
--> src/main.rs:64:48
|
64 | Ok(ResponseJSON::from_serde_value(&unwraped_value)).into_outcome()
| ^^^^^^^^^^^^^^ does not live long enough
...
68 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'v as defined on the body at 53:114...
--> src/main.rs:53:115
|
53 | fn from_data(request: &rocket::Request, data: rocket::Data) -> rocket::data::Outcome<Self, serde_json::Error> {
| ___________________________________________________________________________________________________________________^
54 | | if !request.content_type().map_or(false, |ct| ct.is_json()) {
55 | | println!("Content-Type is not JSON.");
56 | | return rocket::Outcome::Forward(data);
... |
67 | | }
68 | | }
| |_____^
error: aborting due to previous error
由于data_from_reader
,value
和unwraped_value
来自data
,我认为编译器可以推断它具有相同的生命周期,但显然情况并非如此。有什么方法可以说明或做一些在这种情况下会起作用的事情吗?
pub fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: Read,
T: DeserializeOwned,
fn open(self) -> DataStream
rocket::data::DataStream::take
:
fn take(self, limit: u64) -> Take<Self>
答案 0 :(得分:1)
根据@LukasKalbertodt上面的评论,当ResponseJSON拥有serde_json::Value
修改后的代码(按原样粘贴,即使有更好的方法可以链接代码的某些部分)
#![allow(dead_code)]
extern crate serde_json;
extern crate rocket;
extern crate serde;
use serde::ser::Error;
use serde_json::Value;
use rocket::outcome::IntoOutcome;
use std::io::Read;
static NULL: Value = serde_json::Value::Null;
pub struct ResponseJSON { // <-- changed to remove the lifetime parameter
success: bool,
http_code: u16,
data: serde_json::Value, // <- changed to remove the '&'
}
impl ResponseJSON {
pub fn ok() -> ResponseJSON {
ResponseJSON {
success: true,
http_code: 200,
data: Value::Null,
}
}
pub fn http_code(mut self, code: u16) -> ResponseJSON {
self.http_code = code;
self
}
pub fn data(mut self, data: serde_json::Value) -> ResponseJSON { // <- changed to remove the '&'
self.data = data;
self
}
pub fn from_serde_value(json: serde_json::Value) -> ResponseJSON { // <- changed to remove the reference & lifetime parameter
if !json["success"].is_null() {
ResponseJSON::ok()
.http_code(json["http_code"].as_u64().unwrap() as u16)
.data(json.get("data").unwrap_or(&NULL).clone())
} else {
ResponseJSON::ok()
.data(json.pointer("").unwrap().clone())
}
}
}
impl rocket::data::FromData for ResponseJSON {
type Error = serde_json::Error;
fn from_data(request: &rocket::Request, data: rocket::Data) -> rocket::data::Outcome<Self, serde_json::Error> {
if !request.content_type().map_or(false, |ct| ct.is_json()) {
println!("Content-Type is not JSON.");
return rocket::Outcome::Forward(data);
}
let data_from_reader = data.open().take(1<<20);
let value = serde_json::from_reader(data_from_reader);
let unwraped_value : Value = if value.is_ok() { value.unwrap() } else { Value::Null };
if !unwraped_value.is_null() {
Ok(ResponseJSON::from_serde_value(unwraped_value)).into_outcome() // <- changed to remove the '&' in front of `unwraped_value`
} else {
Err(serde_json::Error::custom("Unable to create JSON from reader")).into_outcome()
}
}
}
fn main() {
println!("it compiles & runs");
}
cargo run
输出
Compiling tests v0.1.0 (file:///Users/bgbahoue/Projects.nosync/tests)
Finished dev [unoptimized + debuginfo] target(s) in 1.28 secs
Running `target/debug/tests`
it compiles & runs
我的看法是,在这种情况下,输入参数data
的所有权(生命周期?)会传递给data_from_reader
到value
到unwraped_value
到临时ResponseJSON返回的rocket::data::Outcome
;所以看起来还不错。
使用引用时,临时ResponseJSON没有比函数结束更久,因为它比创建它的serde_json::Value
寿命更长,即unwraped_value
生命周期,即函数的结束;因此编译问题。
虽然不是100%肯定我的解释,但是会喜欢你对此的看法