如何处理为同一路由解析多个JSON的情况?

q3qa4bjr  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(106)

我有一个需求,即我需要根据正文中的JSON在同一HTTP路由中以多种方式处理请求。
路由root("/")中有一个完全不同的JSON对象
喜欢

  • url_验证
{
  "challenge": "b397743d-51c9-40c2-a529-098fd2ff7b4a",
  "token": "1p37CgbHAxiVCmzPhY8epfT2rV7YBSQi",
  "type": "url_verification"
}
  • 接收讯息
{
    "schema": "2.0",
    "header": { 
        "event_id": "f7984f25108f8137722bb63cee927e66",
        "token": "066zT6pS4QCbgj5Do145GfDbbagCHGgF",
        "create_time": "1603977298000000",
        "event_type": "contact.user_group.created_v3",
        "tenant_key": "xxxxxxx",
        "app_id": "cli_xxxxxxxx",
    },
    "event":{
    }
}

下面是我的 rust 代码:

#[derive(Deserialize, Serialize)]
struct UrlVerification {
    challenge: String,
    token: String,
    r#type: String,
}

#[derive(Deserialize, Serialize)]
struct UrlVerificationResp {
    challenge: String,
}

#[tokio::main]
async fn main() {
    pretty_env_logger::init();

    let app = Router::new()
        .route("/", post(url_verification));
        // .route("/", post(msg_recv));  // Overlapping method route

    let addr = SocketAddr::from(([127,0,0,1], 3000));
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

// can not receive a parsed json as a params
async fn url_verification(Json(verified): Json<UrlVerification>) -> impl IntoResponse {
    (StatusCode::OK, Json(UrlVerificationResp {
        challenge: verified.challenge
    }))
}

那么在阿克苏姆,如何优雅地解决这类问题呢?

bis0qfac

bis0qfac1#

serde可以有“untagged enums”,它将尝试反序列化为它可以反序列化的第一个变量。您可以使用它来表示可能是许多格式之一的数据类型。

#[derive(Deserialize)]
#[serde(untagged)]
enum RootRequest {
    UrlVerification(UrlVerification),
    RecieveMessage(ReceiveMessage),
}

这样,您就可以有一个单一的路由来将主体反序列化为这个无标记的枚举类型,并根据实际接收到的请求委托给不同的实现:

#[tokio::main]
async fn main() {
    // ...

    let app = Router::new()
        .route("/", post(root_route));

    // ...
}

async fn root_route(Json(body): Json<RootRequest>) -> Response {
    match body {
        RootRequest::UrlVerification(verified) => {
            url_verification(verified).await.into_response()
        }

        RootRequest::ReceiveMessage(msg) => {
            msg_recv(msg).await.into_response()
        }
    }
}

async fn url_verification(verified: UrlVerification) -> impl IntoResponse {
    // ...
}

async fn recv_msg(msg: ReceiveMessage) -> impl IntoResponse {
    // ...
}

相关问题