100 % local: tus datos nunca salen de tu navegador

JSON a Rust — structs serde listas para derivar

Convierte una muestra JSON en structs de Rust con derives de serde. Los nombres pasan a snake_case sin perder la clave: from_str funciona a la primera.

Instantáneo Privado Cero cookies

Entrada JSON

Salida Rust

Qué hace esta herramienta

Una muestra JSON pasa a ser structs de Rust con derivaciones 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,
}

Los nombres de campo de Rust van en snake_case: firstName pasa a first_name, y #[serde(rename)] conserva la clave, porque un struct que ya no lee su propio JSON sería peor que un nombre poco idiomático. El rename aparece solo donde los dos difieren.

Si solo lees la carga, la opción que quita Serialize te da #[derive(Debug, Deserialize)] y un trait menos que satisfacer.

Las palabras clave, crudas o con sufijo

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

r#type es un identificador crudo: serde ya lo serializa como type, no hace falta atributo. self es de las pocas palabras que Rust no admite ni como identificador crudo —self, Self, crate, super—, así que recibe un guion bajo y un rename.

Lo que viene de serde_json

null, los valores desconocidos, los arrays vacíos y los mezclados acaban todos en serde_json::Value:

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

así que serde_json tiene su sitio en tu Cargo.toml, junto a serde y su característica derive. La ruta se escribe entera en vez de importarse, lo que mantiene la salida válida sea cual sea la organización de tus módulos.

Lo que una muestra no puede decir

Solo null produce un Option. Todo lo demás es obligatorio, porque el documento traía un valor, y «a veces ausente» no es algo que un documento pueda mostrar. Envolver un campo en Option<T> es un retoque; #[serde(default)] es otro, cuando la ausencia debe valer el valor por defecto en vez de un error.

Dos claves que dan el mismo snake_case —fooBar y foo_bar— llevan sufijo en vez de fundirse, y cada una conserva su rename.

Privado por diseño

Todo se ejecuta localmente en tu navegador con JavaScript. Tus datos nunca se suben a un servidor, lo que hace que la herramienta sea segura para contenido sensible y funcione sin conexión.

Preguntas frecuentes

¿Qué hace falta en Cargo.toml?
`serde` con la característica `derive`, y `serde_json` en cuanto un campo lleve un valor desconocido: `Option<serde_json::Value>` y `Vec<serde_json::Value>` vienen de ese crate. La salida usa la ruta completa en vez de importarlo, así que nada se rompe si lo alias de otra manera.
¿Cómo se trata una clave llamada `type` o `self`?
`type` pasa al identificador crudo `r#type`, que serde serializa como `type`: no hace falta atributo. `self` no puede ser identificador crudo en absoluto, así que pasa a `self_` con `#[serde(rename = "self")]` para conservar la clave. Los dos casos salen escritos como el compilador los acepta.
¿Por qué mi identificador de veinte cifras es un `i64`?
Porque es el entero natural de Rust para JSON y llega hasta unos 9,2 × 10¹⁸. Uno más largo no cabe: serde_json informa de un error al deserializar en vez de truncar. Si el campo es un identificador copo de nieve, `u64` gana un bit y `String` es lo que esperan la mayoría de las API.

Convertidores relacionados