Generate Typed Code from JSON — TypeScript, Python, Go, Rust & More

Convert JSON to typed code in 8 programming languages. See how type inference works, with before-and-after examples for TypeScript interfaces, Python dataclasses, Go structs, Rust serde, and more.

Команда JSONTechMarch 25, 202611 min

Зачем генерировать код из JSON?

Каждый проект, который использует JSON API, в конечном итоге нуждается в типизированных моделях. Вы копируете пример ответа в свой редактор, смотрите на поля и начинаете вручную писать интерфейс или структуру. Это работает — пока нагрузка не содержит 40 полей, трех уровней вложенности и массива полиморфных объектов. Тогда это становится утомительным, подверженным ошибкам и медленным.

Генератор кода устраняет этот ручной шаг. Вставьте образец JSON, выберите язык и получите готовые к производству определения типов за считанные секунды. Преимущества очевидны:

  • Экономия времени — генерация типов для нагрузки из 50 полей занимает секунды вместо минут.
  • Безопасность типов — ваш компилятор или среда выполнения обнаруживает несоответствия до того, как они попадут в производство.
  • Меньше шаблонного кода — больше не нужно вручную писать геттеры, сеттеры, теги JSON или аннотации serde.
  • Согласованность — каждый член команды получает одни и те же модели из одних и тех же исходных данных.

Как работает вывод типов

Генератор JSON в код считывает ваши образцы данных и выводит тип для каждого значения. Строки становятся string, числа становятся int или float в зависимости от наличия десятичной точки, булевы значения сопоставляются напрямую, а null создает обертку, которая может быть необязательной/nullable. Объекты становятся именованными типами (структуры, классы, интерфейсы), а массивы становятся типизированными коллекциями элементов.

Вот как типы JSON сопоставляются с языками:

Тип JSONTypeScriptPythonJavaGoRustSwift
строкаstringstrStringstringStringString
число (int)numberintintint64i64Int
число (float)numberfloatdoublefloat64f64Double
булевоbooleanboolbooleanboolboolBool
nullnullNonenull*T (указатель)Option<T>T?
объектinterfacedataclassclass (POJO)structstructstruct (Codable)
массивT[]list[T]List<T>[]TVec<T>[T]

Ключевое понимание: генератор знает только то, что он видит. Если ваши образцы данных имеют 42 для поля, которое также может быть 42.5, генератор выберет int вместо float. Используйте репрезентативные образцы данных для точных типов.

Пример входных данных

Мы будем использовать этот JSON в примерах ниже. Он охватывает строки, числа, булевы значения, вложенный объект и массив:

{
  "id": 1,
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "active": true,
  "score": 97.5,
  "address": {
    "street": "123 Main St",
    "city": "Portland",
    "zip": "97201"
  },
  "tags": ["admin", "editor"]
}

Интерфейсы TypeScript из JSON

TypeScript является наиболее распространенной целью. Генератор создает интерфейс для каждого объекта, используя имена полей в качестве ключей свойств:

interface Address {
  street: string;
  city: string;
  zip: string;
}

interface Root {
  id: number;
  name: string;
  email: string;
  active: boolean;
  score: number;
  address: Address;
  tags: string[];
}

Каждое поле типизировано, вложенный объект address получает свой собственный интерфейс, а tags выводится как string[] из его содержимого. Вы можете вставить это прямо в свой проект и начать использовать с полной автозаполнением и проверками на этапе компиляции.

Датаклассы Python из JSON

Декоратор @dataclass в Python автоматически генерирует методы __init__, __repr__ и сравнения. В сочетании с подсказками типов это самый чистый способ определения моделей JSON в Python:

from dataclasses import dataclass

@dataclass
class Address:
    street: str
    city: str
    zip: str

@dataclass
class Root:
    id: int
    name: str
    email: str
    active: bool
    score: float
    address: Address
    tags: list[str]

Сочетайте это с библиотекой, такой как dacite или cattrs, чтобы десериализовать словари JSON непосредственно в эти экземпляры датаклассов.

POJO Java из JSON

Java требует больше церемоний — поля, конструктор и геттеры/сеттеры. Генератор экономит больше всего времени здесь:

public class Address {
    private String street;
    private String city;
    private String zip;

    public String getStreet() { return street; }
    public void setStreet(String street) { this.street = street; }
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public String getZip() { return zip; }
    public void setZip(String zip) { this.zip = zip; }
}

public class Root {
    private int id;
    private String name;
    private String email;
    private boolean active;
    private double score;
    private Address address;
    private List<String> tags;

    // геттеры и сеттеры...
}

Сгенерированные POJO работают напрямую с Jackson, Gson или любой другой библиотекой сериализации JSON в экосистеме Java.

Структуры Go из JSON

Структуры Go используют теги полей для управления сериализацией JSON. Генератор производит идиоматичный Go с экспортируемыми полями и тегами json:"...":

type Address struct {
    Street string `json:"street"`
    City   string `json:"city"`
    Zip    string `json:"zip"`
}

type Root struct {
    ID      int64    `json:"id"`
    Name    string   `json:"name"`
    Email   string   `json:"email"`
    Active  bool     `json:"active"`
    Score   float64  `json:"score"`
    Address Address  `json:"address"`
    Tags    []string `json:"tags"`
}

Теги обеспечивают, что json.Unmarshal сопоставляет строчные ключи JSON с экспортируемыми (с заглавной буквы) полями Go. Имена полей автоматически становятся в PascalCase, а id становится ID в соответствии с соглашениями именования Go.

Структуры Rust из JSON

Rust использует крейт serde для сериализации. Генератор добавляет необходимые макросы derive:

use serde::{Deserialize, Serialize};

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

#[derive(Debug, Serialize, Deserialize)]
pub struct Root {
    pub id: i64,
    pub name: String,
    pub email: String,
    pub active: bool,
    pub score: f64,
    pub address: Address,
    pub tags: Vec<String>,
}

С помощью serde_json вы можете десериализовать строку JSON в эти структуры с помощью одного вызова serde_json::from_str. Компилятор обеспечивает наличие каждого поля и его правильный тип.

Swift Codable из JSON

Протокол Codable в Swift позволяет встроенное кодирование и декодирование JSON без внешних зависимостей:

struct Address: Codable {
    let street: String
    let city: String
    let zip: String
}

struct Root: Codable {
    let id: Int
    let name: String
    let email: String
    let active: Bool
    let score: Double
    let address: Address
    let tags: [String]
}

Используйте JSONDecoder().decode(Root.self, from: data), чтобы разобрать данные JSON непосредственно в эти структуры. Swift автоматически выводит ключи кодирования из имен свойств.

Обработка вложенных объектов и массивов

Вложенные объекты — самая интересная часть генерации кода. Когда генератор сталкивается со значением объекта внутри другого объекта, он создает отдельный именованный тип. Обычно соглашение о наименовании основано на имени поля:

  • Поле с именем address, содержащим объект, производит тип, называемый Address.
  • Поле с именем shipping_details производит ShippingDetails (в PascalCase).
  • Глубоко вложенные объекты следуют той же схеме рекурсивно — address с вложенным объектом coordinates производит как типы Address, так и Coordinates.

Массивы объектов обрабатываются аналогично. Если items — это массив объектов, генератор исследует первый элемент (или объединяет все элементы), чтобы вывести тип и создает тип с единственным именем, например, Item.

Массивы примитивов (["admin", "editor"]) просты — они становятся string[], Vec<String>, []string и т. д. в зависимости от целевого языка.

Советы для лучшего сгенерированного кода

Качество сгенерированных типов полностью зависит от качества ваших входных данных. Несколько практических советов:

  • Используйте репрезентативные образцы данных. Включите хотя бы один пример каждого варианта поля. Если поле может быть null, включите значение null, чтобы генератор пометил его как необязательное.
  • Сохраняйте согласованность типов. Если id является числом в некоторых записях и строкой в других, генератор должен выбрать одно или использовать объединенный тип. Сначала очистите свои образцы данных.
  • Переименуйте корневой тип. Большинство генераторов по умолчанию используют Root в качестве верхнего уровня. Переименуйте его во что-то значимое, например, User или ApiResponse, после генерации.
  • Упрощайте перед генерацией, если вам нужна только подсистема структуры. Обрежьте свой образец JSON до только тех полей, которые вам важны.
  • Проверяйте крайние случаи. Пустые массивы ([]) не могут быть типизированы без контекста. Заполните их хотя бы одним элементом, чтобы генератор знал тип элемента.
  • Просматривайте и корректируйте. Сгенерированный код — это отправная точка. Возможно, вам захочется переименовать поля, скорректировать ширину целых чисел, добавить аннотации валидации или пометить поля как необязательные на основе ваших знаний о предметной области.

Попробуйте сами

Генерируйте типизированный код мгновенно: Вставьте любой JSON в наш JSON в код генератор и получите готовые к производству типы для TypeScript, Python, Java, Go, Rust, Swift, Kotlin и C#. Регистрация не требуется.

Похожие инструменты