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.

JSONTech 团队March 25, 202611 min

为什么从 JSON 生成代码?

每个使用 JSON API 的项目最终都需要类型化模型。你将一个示例响应复制到编辑器中,目测字段,然后开始手动编写接口或结构体。这是可行的——直到负载有 40 个字段、三层嵌套和一个多态对象数组。那时这就变得繁琐、容易出错且速度慢。

代码生成器消除了这个手动步骤。粘贴一个 JSON 示例,选择一种语言,几秒钟内就能得到生产就绪的类型定义。好处是显而易见的:

  • 节省时间 — 为一个 50 字段的负载生成类型只需几秒钟,而不是几分钟。
  • 类型安全 — 你的编译器或运行时会在它们到达生产环境之前捕获不匹配。
  • 减少样板代码 — 不再手动编写获取器、设置器、JSON 标签或序列化注解。
  • 一致性 — 每个团队成员从相同的源数据中获得相同的模型。

类型推断是如何工作的

JSON 到代码生成器读取你的示例数据并推断每个值的类型。字符串变为 string,数字根据小数点的存在变为 intfloat,布尔值直接映射,null 生成一个可选/可空的包装。对象变为命名类型(结构体、类、接口),数组变为其元素的类型集合。

以下是 JSON 类型在不同语言中的映射:

JSON 类型TypeScriptPythonJavaGoRustSwift
stringstringstrStringstringStringString
number (int)numberintintint64i64Int
number (float)numberfloatdoublefloat64f64Double
booleanbooleanboolbooleanboolboolBool
nullnullNonenull*T (指针)Option<T>T?
objectinterfacedataclassclass (POJO)structstructstruct (Codable)
arrayT[]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"]
}

从 JSON 生成 TypeScript 接口

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[]。你可以将其直接粘贴到项目中,并开始使用它,享受完整的自动补全和编译时检查。

从 JSON 生成 Python 数据类

Python 的 @dataclass 装饰器自动生成 __init____repr__ 和比较方法。结合类型提示,这是在 Python 中定义 JSON 模型的最简洁方式:

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]

将此与 dacitecattrs 等库配合使用,可以直接将 JSON 字典反序列化为这些数据类实例。

从 JSON 生成 Java POJO

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;

    // getters and setters...
}

生成的 POJO 可以直接与 Jackson、Gson 或 Java 生态系统中的任何其他 JSON 序列化库一起使用。

从 JSON 生成 Go 结构体

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 字段。字段名称自动采用 Pascal 大小写,id 变为 ID,遵循 Go 命名约定。

从 JSON 生成 Rust 结构体

Rust 使用 serde crate 进行序列化。生成器添加必要的派生宏:

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,你可以通过一次调用 serde_json::from_str 将 JSON 字符串反序列化为这些结构体。编译器强制确保每个字段都存在且类型正确。

从 JSON 生成 Swift Codable

Swift 的 Codable 协议使得内置 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(Pascal 大小写)。
  • 深度嵌套的对象遵循相同的模式递归——一个带有嵌套 coordinates 对象的 address 生成 AddressCoordinates 类型。

对象数组的处理方式类似。如果 items 是一个对象数组,生成器检查第一个元素(或合并所有元素)以推断类型,并创建一个单数命名的类型,如 Item

原始数组(["admin", "editor"])则比较简单——它们变为 string[]Vec<String>[]string 等,具体取决于目标语言。

提高生成代码质量的技巧

生成类型的质量完全取决于输入数据的质量。一些实用的技巧:

  • 使用具有代表性的示例数据。 包含每个字段变体的至少一个示例。如果一个字段可以是 null,请包含一个空值,以便生成器将其标记为可选。
  • 保持类型一致。 如果 id 在某些记录中是数字,而在其他记录中是字符串,生成器必须选择一个或使用联合类型。首先清理你的示例数据。
  • 重命名根类型。 大多数生成器将顶层名称默认为 Root。生成后将其重命名为有意义的名称,如 UserApiResponse
  • 在生成之前扁平化 如果你只需要结构的子集。将你的 JSON 示例修剪到你关心的字段。
  • 检查边缘情况。 空数组([])在没有上下文的情况下无法被类型化。用至少一个元素填充它们,以便生成器知道项目类型。
  • 审查和调整。 生成的代码是一个起点。你可能想重命名字段、调整整数宽度、添加验证注释或根据你的领域知识标记可选字段。

亲自尝试

立即生成类型化代码: 将任何 JSON 粘贴到我们的 JSON 到代码 生成器中,获取 TypeScript、Python、Java、Go、Rust、Swift、Kotlin 和 C# 的生产就绪类型。无需注册。

相关工具