如何将 json 模式作为数据传递给 actix web?

问题描述

我想将预编译的 json 模式传递给 actix web,但是编译器抱怨用于创建 Value 的借用 JSONSchema 寿命不够长。有没有办法解决这个问题?

示例:

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,但我们可以解决这个问题。首先,我们使用 ValueBox::new 放在堆栈上。然后我们使用 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
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...