< 返回版块

mike 发表于 2022-02-07 17:20

Tags:axum, 结构体嵌套

我在用axum 实现一个简单的功能 通常与前端交互的返回值都是一个嵌套的json 例如{err_code:"1000",err_msg:"test",data:""} data 是一个要返回的结构体

我想把这里的逻辑抽象一下类似下面这样

use axum::Json;
use serde::Serialize;

#[derive(Serialize)]
pub struct Response<T>{
	err_code:u32,
	err_msg:String,
	data:T,
}


pub fn success<T>(data:T) -> Json<Response> {

	let res = Response{err_code:0,err_msg:"".to_string(),data};
	Json(res)
}

go 里面很容易就可以这样写

type Response struct {
	ErrorCode int         `json:"code"`
	ErrorMsg  string      `json:"message"`
	Success   bool        `json:"success"`
	Data      interface{} `json:"data"`
}

但是这样写,怎么编译都不太对,请教一下各位大佬,结构体能像go 一样嵌套结构体吗? 我应该怎样实现

评论区

写评论
郭大路 2022-02-13 14:47

mark

作者 mike 2022-02-08 09:24

感谢大佬的建议,大佬能否讲下为什么指定一下SerializeTrait的实现

--
👇
98P: 我感觉你可以在结构体上的T指定实现SerializeTrait

#[derive(Serialize)]
struct Response<T: Serialize> {
    data: T,
}

或者在函数参数上指定实现SerializeTrait

fn success<T: Serialize>(data: T) -> Json<Response> {
    Json(Response{ data })
}
作者 mike 2022-02-08 09:22

感谢大佬,已解决,非常感谢~

--
👇
c5soft: 将函数success的返回值改一下,加上泛型 T 就对了

use axum::{routing::get, Json, Router};
use serde::Serialize;
use std::net::SocketAddr;

#[tokio::main]
async fn main() {
    // build our application with a route
    let app = Router::new().route("/", get(call_success));

    // run our app with hyper
    // `axum::Server` is a re-export of `hyper::Server`
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    println!("listening on http://{}", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}


#[derive(Serialize)]
pub struct Response<T> {
    err_code: u32,
    err_msg: String,
    data: T,
}

pub fn success<T>(data: T) -> Json<Response<T>> {
    let res = Response {
        err_code: 0,
        err_msg: "".to_string(),
        data,
    };
    Json(res)
}


#[derive(Serialize)]
struct User {
    id: u64,
    username: String,
}


async fn call_success() -> Json<Response<User>> {
    let data = User {
        id: 123,
        username: String::from("Jack"),
    };
    success(data)
}

stirlingx 2022-02-08 09:13

我写了一个demo,刚好解决这问题

https://github.com/liyue201/rust-rest-demo/blob/5a8f0efa2f876f13630d6955e7c3efe9ee5dc3a1/src/server/code.rs#L39

c5soft 2022-02-08 06:42

将函数success的返回值改一下,加上泛型 T 就对了

use axum::{routing::get, Json, Router};
use serde::Serialize;
use std::net::SocketAddr;

#[tokio::main]
async fn main() {
    // build our application with a route
    let app = Router::new().route("/", get(call_success));

    // run our app with hyper
    // `axum::Server` is a re-export of `hyper::Server`
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    println!("listening on http://{}", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}


#[derive(Serialize)]
pub struct Response<T> {
    err_code: u32,
    err_msg: String,
    data: T,
}

pub fn success<T>(data: T) -> Json<Response<T>> {
    let res = Response {
        err_code: 0,
        err_msg: "".to_string(),
        data,
    };
    Json(res)
}


#[derive(Serialize)]
struct User {
    id: u64,
    username: String,
}


async fn call_success() -> Json<Response<User>> {
    let data = User {
        id: 123,
        username: String::from("Jack"),
    };
    success(data)
}

98P 2022-02-07 20:22

我感觉你可以在结构体上的T指定实现SerializeTrait

#[derive(Serialize)]
struct Response<T: Serialize> {
    data: T,
}

或者在函数参数上指定实现SerializeTrait

fn success<T: Serialize>(data: T) -> Json<Response> {
    Json(Response{ data })
}
1 共 6 条评论, 1 页