100 % locale — i tuoi dati non lasciano mai il tuo browser

JSON in Rust — struct serde pronte da derivare

Trasforma un campione JSON in struct Rust con i derive di serde. I nomi diventano snake_case senza perdere la chiave: from_str funziona al primo colpo.

Istantaneo Privato Zero cookie

Input JSON

Output Rust

Che cosa fa questo strumento

Un campione JSON diventa struct Rust con le derivazioni serde.

{ "id": 1, "firstName": "Ada", "address": { "city": "Paris" } }
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct Root {
    pub id: i64,
    #[serde(rename = "firstName")]
    pub first_name: String,
    pub address: Address,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Address {
    pub city: String,
}

I nomi dei campi Rust sono in snake_case: firstName diventa first_name — e #[serde(rename)] conserva la chiave, perché una struct che non rilegge il proprio JSON sarebbe peggio di un nome poco idiomatico. Il rename compare solo dove i due divergono.

Se leggi soltanto il carico, l’opzione che toglie Serialize ti dà #[derive(Debug, Deserialize)] e un trait in meno da soddisfare.

Le parole chiave, grezze o con suffisso

{ "type": "user", "self": "/users/1" }
    pub r#type: String,
    #[serde(rename = "self")]
    pub self_: String,

r#type è un identificatore grezzo: serde lo serializza già come type, nessun attributo serve. self è tra le poche parole che Rust non accetta nemmeno come identificatore grezzo — self, Self, crate, super — quindi prende un trattino basso e un rename.

Ciò che viene da serde_json

null, i valori ignoti, gli array vuoti e quelli misti finiscono tutti in serde_json::Value:

    pub nickname: Option<serde_json::Value>,
    pub tags: Vec<serde_json::Value>,

quindi serde_json ha il suo posto nel tuo Cargo.toml, accanto a serde con la feature derive. Il percorso è scritto per intero invece che importato, il che tiene valida l’uscita qualunque sia l’organizzazione dei tuoi moduli.

Ciò che un campione non può dire

Solo null produce un Option. Tutto il resto è obbligatorio, perché il documento aveva un valore — e «a volte assente» non è qualcosa che un documento possa mostrare. Avvolgere un campo in Option<T> è una modifica; #[serde(default)] è l’altra, quando l’assenza deve valere il valore predefinito invece di un errore.

Due chiavi che danno lo stesso snake_case — fooBar e foo_bar — prendono un suffisso invece di fondersi, e ciascuna conserva il proprio rename.

Privato per progettazione

Tutto viene eseguito localmente nel browser con JavaScript. I tuoi dati non vengono mai caricati, quindi lo strumento è sicuro per contenuti sensibili e funziona anche offline.

Domande frequenti

Che cosa serve in Cargo.toml?
`serde` con la feature `derive`, e `serde_json` non appena un campo porta un valore ignoto: `Option<serde_json::Value>` e `Vec<serde_json::Value>` vengono da quel crate. L’uscita usa il percorso completo invece di importarlo, così nulla si rompe se lo rinomini.
Come viene trattata una chiave chiamata `type` o `self`?
`type` diventa l’identificatore grezzo `r#type`, che serde serializza come `type` — nessun attributo necessario. `self` non può essere un identificatore grezzo, quindi diventa `self_` con `#[serde(rename = "self")]` per conservare la chiave. Entrambi i casi escono scritti come il compilatore li accetta.
Perché il mio identificatore di venti cifre è un `i64`?
Perché è l’intero naturale di Rust per JSON e arriva a circa 9,2 × 10¹⁸. Uno più lungo non ci sta: serde_json segnala un errore alla deserializzazione invece di troncare. Se il campo è un identificatore snowflake, `u64` guadagna un bit e `String` è ciò che la maggior parte delle API si aspetta davvero.

Convertitori correlati