如何将 json 模式作为数据传递给 actix web?
How can I pass a json schema as data to actix web?
我想将预编译的 json 模式传递给 actix web,但编译器抱怨用于创建 JSONSchema
的借用 Value
寿命不够长。有没有办法解决这个问题?
示例:
use jsonschema::JSONSchema;
use serde_json::from_str;
use actix_web::{web, get, App, HttpServer, HttpResponse, Responder};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let schema_str = include_str!("schema.json");
let schema_value = from_str(schema_str).unwrap();
let schema_compiled = JSONSchema::compile(&schema_value).unwrap();
App::new()
.data(schema_compiled) // fixme: compiles if commented out
.service(index)
})
.bind("0.0.0.0:8080")?
.run()
.await
}
#[get("/")]
async fn index<'a>(_schema: web::Data<JSONSchema<'a>>) -> impl Responder {
HttpResponse::Ok().finish() // todo: use schema for something
}
rustc 错误:
error[E0597]: `schema_value` does not live long enough
--> src/main.rs:10:51
|
10 | let schema_compiled = JSONSchema::compile(&schema_value).unwrap();
| --------------------^^^^^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `schema_value` is borrowed for `'static`
...
14 | })
| - `schema_value` dropped here while still borrowed
我是 Rust 的新手,如果这是一个变相的通用 Rust 问题,我深表歉意(一旦我的理解得到改善,我会很乐意用更小的可重现性来修改这个问题)。
问题的根本原因是 JSONSchema
不拥有 Value
,但我们可以解决这个问题。首先,我们使用 Box::new
将 Value
放入堆栈。然后我们使用 Box::leak
泄漏一个引用(它将持续应用程序的生命周期)。最后我们使用 Arc::new
以便我们可以在内部范围内的模式上调用 clone()
(这最后一步允许您将模式代码移动到其他地方,这很好)。
use jsonschema::JSONSchema;
use serde_json::{from_str, Value};
use actix_web::{web, get, App, HttpServer, HttpResponse, Responder};
use std::sync::Arc;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let schema_str = include_str!("schema.json");
let schema_value: &'static Value = Box::leak(Box::new(from_str(schema_str).unwrap()));
let schema_compiled: JSONSchema<'static> = JSONSchema::compile(schema_value).unwrap();
let schema_arc = Arc::new(schema_compiled);
HttpServer::new(move || {
App::new()
.data(schema_arc.clone())
.service(index)
})
.bind("0.0.0.0:8080")?
.run()
.await
}
#[get("/")]
async fn index<'a>(_schema: web::Data<Arc<JSONSchema<'a>>>) -> impl Responder {
HttpResponse::Ok().finish() // todo: use schema for something
}
我想将预编译的 json 模式传递给 actix web,但编译器抱怨用于创建 JSONSchema
的借用 Value
寿命不够长。有没有办法解决这个问题?
示例:
use jsonschema::JSONSchema;
use serde_json::from_str;
use actix_web::{web, get, App, HttpServer, HttpResponse, Responder};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let schema_str = include_str!("schema.json");
let schema_value = from_str(schema_str).unwrap();
let schema_compiled = JSONSchema::compile(&schema_value).unwrap();
App::new()
.data(schema_compiled) // fixme: compiles if commented out
.service(index)
})
.bind("0.0.0.0:8080")?
.run()
.await
}
#[get("/")]
async fn index<'a>(_schema: web::Data<JSONSchema<'a>>) -> impl Responder {
HttpResponse::Ok().finish() // todo: use schema for something
}
rustc 错误:
error[E0597]: `schema_value` does not live long enough
--> src/main.rs:10:51
|
10 | let schema_compiled = JSONSchema::compile(&schema_value).unwrap();
| --------------------^^^^^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `schema_value` is borrowed for `'static`
...
14 | })
| - `schema_value` dropped here while still borrowed
我是 Rust 的新手,如果这是一个变相的通用 Rust 问题,我深表歉意(一旦我的理解得到改善,我会很乐意用更小的可重现性来修改这个问题)。
问题的根本原因是 JSONSchema
不拥有 Value
,但我们可以解决这个问题。首先,我们使用 Box::new
将 Value
放入堆栈。然后我们使用 Box::leak
泄漏一个引用(它将持续应用程序的生命周期)。最后我们使用 Arc::new
以便我们可以在内部范围内的模式上调用 clone()
(这最后一步允许您将模式代码移动到其他地方,这很好)。
use jsonschema::JSONSchema;
use serde_json::{from_str, Value};
use actix_web::{web, get, App, HttpServer, HttpResponse, Responder};
use std::sync::Arc;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let schema_str = include_str!("schema.json");
let schema_value: &'static Value = Box::leak(Box::new(from_str(schema_str).unwrap()));
let schema_compiled: JSONSchema<'static> = JSONSchema::compile(schema_value).unwrap();
let schema_arc = Arc::new(schema_compiled);
HttpServer::new(move || {
App::new()
.data(schema_arc.clone())
.service(index)
})
.bind("0.0.0.0:8080")?
.run()
.await
}
#[get("/")]
async fn index<'a>(_schema: web::Data<Arc<JSONSchema<'a>>>) -> impl Responder {
HttpResponse::Ok().finish() // todo: use schema for something
}