Risposta JSON custom in Axum

Mattepuffo's logo
Risposta JSON custom in Axum

Risposta JSON custom in Axum

In pratica voglio che il mio controller Axum risponda con array di oggetti, ma dentro ad oggetto root data.

Quindi una cosa del genere:

{
	"data": [
		{....},
		{....},
		{....},
		{....}
	]
}

Ovviamente per farlo dobbiamo partire dalle nostre struct.

Qui sotto il mio esempio (considerate che sto usando anche sqlx):

#[derive(Serialize)]
pub struct AnagraficaResponse {
    pub data: Vec<Anagrafica>,
}

#[derive(Serialize, FromRow, Deserialize)]
pub struct Anagrafica {
    pub ag_id: i64,
    pub ag_denominazione: Option<String>,
    pub ag_alias: Option<String>,
    pub ag_email: Option<String>,
    pub ag_piva: Option<String>,
    pub ag_cf: Option<String>,
    pub ag_pec: Option<String>,
    pub ag_codice_ident: Option<String>,
    pub ag_telefono: Option<String>,
    pub ag_indirizzo: Option<String>,
    pub ag_cap: Option<String>,
    pub ag_citta: Option<String>,
    pub ag_paese: Option<String>,
    pub ag_web: Option<String>,
    pub ag_logo: Option<String>,
    pub ag_note: Option<String>,
    pub ag_utente_fk: i32,
    pub ag_provincia: Option<String>,
    pub ag_data_aggiunta: Option<NaiveDateTime>,
    pub ag_data_modifica: Option<NaiveDateTime>,
}

Quindi incapsuliamo il nostro oggetto dentro un altro che rappresenta la root.

Questo il service:

pub async fn get_by_utente(state: &AppState, user_id: i64) -> Result<Vec<Anagrafica>, Error> {
    let items = sqlx::query_as::<MySql, Anagrafica>(
        "SELECT * FROM anag_generali
         WHERE ag_utente_fk = ?
         ORDER BY ag_alias",
    )
    .bind(user_id)
    .fetch_all(&state.pool)
    .await?;

    Ok(items)
}

Infine il controller:

pub async fn get_by_utente(
    State(state): State<AppState>,
    user: AuthenticatedUser,
) -> Json<AnagraficaResponse> {
    let user_id = user.claims.data.id;
    match anagrafiche_service::get_by_utente(&state, user_id).await {
        Ok(data) => {
            let mapped = data.into_iter().map(Anagrafica::from).collect();
            Json(AnagraficaResponse { data: mapped })
        }
        Err(e) => {
            error!("Errore in get_by_utente (utente_id={}): {:?}", user_id, e);
            Json(AnagraficaResponse { data: vec![] })
        }
    }
}

Considerate anche che la rotta è protetta da token, che potrei usare librerie che voi non state usando, ecc.

Comunque l'importante è che capiate il meccanismo.

Enjoy!


Condividi

Commentami!