Перейти к содержимому

Преобразование JSON в структуры Rust Serde — Numio

Генерирует структуры Rust с derive Serialize и Deserialize из serde по примеру JSON. Поля получают snake_case с атрибутом rename_all, ключи, отсутствующие в некоторых элементах массива, становятся Option<T>, а значения null — serde_json::Value.

Типизировать ответ стороннего API перед десериализацией через serde_json в клиенте reqwest.

JSON

Rust Serde

Когда пригодится

  • Типизировать ответ стороннего API перед десериализацией через serde_json в клиенте reqwest.
  • Написать структуры для JSON-конфига или фикстуры в Rust CLI или сервисе на Axum.

Как пользоваться

  1. Вставьте пример JSON; если поле необязательное, добавьте элементы массива как с ним, так и без него.
  2. Откройте настройки и выберите в Property Name Format стиль ключей в вашем JSON (по умолчанию camelCase). Он задаёт #[serde(rename_all = ...)]; ключи, которые ему не соответствуют, получают #[serde(rename = ...)].
  3. Скопируйте код и добавьте в Cargo.toml serde (с derive), serde_derive и serde_json, как того требуют сгенерированные строки use.

Ввод JSON

{
  "orderId": "A-1001",
  "total": 19.5,
  "paid": true,
  "coupon": null,
  "items": [
    { "sku": "PEN-01", "qty": 2 },
    { "sku": "BOOK-7", "qty": 1, "giftWrap": true }
  ]
}

Структуры Rust (serde)

use serde_derive::Deserialize;
use serde_derive::Serialize;
use serde_json::Value;

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Root {
    pub order_id: String,
    pub total: f64,
    pub paid: bool,
    pub coupon: Value,
    pub items: Vec<Item>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Item {
    pub sku: String,
    pub qty: i64,
    pub gift_wrap: Option<bool>,
}

Подробности и ограничения

Генерация выполняется в браузере WebAssembly-модулем json_typegen; на сервер ничего не отправляется.

Целые числа становятся i64, дробные — f64. null и пустые массивы дают serde_json::Value и Vec<Value>; замените их конкретными типами, например Option<String>.

Ключевые слова Rust переименовываются: ключ type становится type_field с #[serde(rename = "type")].

Каждая структура, помимо Serialize и Deserialize, выводит Default, Debug, Clone и PartialEq; удалите ненужные.

FAQ

Что меняет настройка Property Name Format?

Она описывает, как записаны ключи в вашем JSON, а не имена полей Rust. Поля всегда в snake_case; настройка выбирает значение rename_all, чтобы serde сопоставлял их обратно с camelCase, kebab-case, PascalCase и т. д.

Как определяются необязательные поля?

Если у объектов в одном массиве разные ключи, ключи, отсутствующие в некоторых элементах, становятся Option<T>. Поле, присутствующее во всех элементах примера, не считается необязательным, даже если ваш API иногда его опускает.

Может ли корень JSON быть массивом?

Да. Корневой массив даёт pub type Root = Vec<Root2>; со struct Root2 для элементов.

Спецификации и справка