#rust #serde #actix-web
#Ржавчина #серде #actix-web
Вопрос:
С примером, приведенным в документации для actix_web::web::Query
, как я могу response_type
прибегнуть к None
при предоставлении неизвестного варианта?
Если у меня есть следующее:
use actix_web::{web, App, HttpServer};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub enum ResponseType {
Token,
Code,
}
#[derive(Deserialize)]
pub struct AuthRequest {
id: u64,
response_type: Option<ResponseType>,
}
async fn index(web::Query(info): web::Query<AuthRequest>) -> String {
format!(
"Authorization request for client with id={} and type={:?}!",
info.id, info.response_type
)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().route("/", web::get().to(index)))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
И я посещаю http://localhost:8080/?id=1amp;response_type=foo
, я получаю этот 400- й ответ:
Ошибка десериализации запроса: неизвестный вариант
foo
, ожидаемыйToken
илиCode
Когда я вместо этого хотел бы, чтобы он принимал только значения Перечисления в качестве допустимых значений, и если значение не указано или указано недопустимое значение, я хочу, чтобы оно было установлено None
равным.
Ответ №1:
С этим можно справиться с помощью deserialize_with .
use actix_web::{web, App, HttpServer};
use serde::Deserialize;
use serde::de::{Deserializer};
#[derive(Debug, Deserialize)]
pub enum ResponseType {
Token,
Code,
}
fn from_response_type<'de, D>(deserializer: D) -> Result<Option<ResponseType>, D::Error>
where
D: Deserializer<'de>,
{
let res: Option<ResponseType> = Deserialize::deserialize(deserializer).unwrap_or(None);
Ok(res)
}
#[derive(Debug, Deserialize)]
pub struct AuthRequest {
id: u64,
#[serde(deserialize_with = "from_response_type")]
response_type: Option<ResponseType>,
}
async fn index(web::Query(info): web::Query<AuthRequest>) -> String {
format!(
"Authorization request for client with id={} and type={:?}!",
info.id, info.response_type
)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().route("/", web::get().to(index)))
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Любое недопустимое значение считается a None
. Ключевая строка
let res: Option<ResponseType> = Deserialize::deserialize(deserializer).unwrap_or(None);