JSON 转 Python Dataclass

即时从 JSON 生成 Python dataclass,支持 @dataclass、Pydantic v2 BaseModel 和 TypedDict,处理嵌套对象、数组、可选字段和自定义根类名。免费,在浏览器中运行。

  • 在浏览器中处理
  • 数据不离开你的设备
  • 免费 · 无需注册
留空时使用 Root。修改名称后,等待 300 毫秒自动生成。
模式 选择 @dataclass、Pydantic v2 或 TypedDict,切换后立即重新生成。
用含嵌套对象、数组和 null 的示例替换 JSON,并按当前设置立即生成。
清空 JSON、输出和状态,保留根名和所选模式。在工具内按 Ctrl/⌘+L 还会清空根名。
输入合法 JSON,不能带注释或末尾逗号。停止输入 300 毫秒后自动生成;JSON 无效时会清空输出并显示错误。
Python 输出
复制当前显示的完整 Python 输出。输出为空时不复制。
将当前完整输出保存为 .py 文件。文件名使用小写根名,ASCII 字母、数字和下划线以外的字符替换为下划线。输出为空时不下载。

输入 JSON 或载入示例以生成 Python。

示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。

类型映射

  • null → Optional[Any] = None
  • 字符串 → str
  • 整数 → int
  • 浮点数 → float
  • 布尔值 → bool
  • 数组 → List[T]
  • 混合数组 → List[Union[T1, T2]]
  • 嵌套对象 → 独立类

示例

给定如下 JSON:

{"user": {"first_name": "Alice", "age": 30}, "tags": ["admin"], "note": null}

@dataclass 模式下生成:

from dataclasses import dataclass
from typing import Any, List, Optional

@dataclass
class User:
    first_name: str
    age: int

@dataclass
class Root:
    user: User
    tags: List[str]
    note: Optional[Any] = None

示例:嵌套对象与缺失的键

输入:

{"id": 7, "title": "Release notes", "author": {"name": "Alice", "email": null}, "tags": ["python", "json"], "score": 4.5, "comments": [{"user": "bob", "text": "nice"}, {"user": "carol"}]}

@dataclass 模式的输出:

from dataclasses import dataclass
from typing import Any, List, Optional

@dataclass
class Author:
  name: str
  email: Optional[Any] = None

@dataclass
class CommentsItem:
  user: str
  text: Optional[str] = None

@dataclass
class Root:
  id: int
  title: str
  author: Author
  tags: List[str]
  score: float
  comments: List[CommentsItem]

类的顺序保证每个类在被使用前已定义。第二条评论缺少 text,所以它是 Optional[str] = None。

dataclass、Pydantic 还是 TypedDict

三种模式描述的结构相同,运行时行为不同(Python 3.12、Pydantic 2.13 实测):

root = Root(**json.loads(raw))
type(root.author)          # <class 'dict'>, not Author
root = Root.model_validate(json.loads(raw))   # Pydantic mode
root.comments[1]           # CommentsItem(user='carol', text=None)
  • @dataclass 不校验也不转换。Root(**data) 里的嵌套对象仍是普通 dict,类型不对也照样接受。数据可信时再用,或者自己转换嵌套字段。
  • Pydantic 会校验类型并构造嵌套模型,适合处理你控制不了的 API 响应。model_validate_json(raw) 一步完成解析和校验。
  • TypedDict 只给类型检查器描述 dict 的结构,运行时什么都不检查。所有键默认都是必需的,工具把只在部分元素里出现的键写成 NotRequired[...](PEP 655,Python 3.11+ 在 typing 中,更早版本用 typing_extensions)。Optional[...] 只表示值可以是 None,键仍然必需。

示例:带缺失键的 TypedDict

两个商品:note 在第一个里为 null、在第二个里缺失,discount 只出现在第二个里(根类名 Product,TypedDict 模式):

[{"id": 1, "sku": "PEN-01", "price": 2, "note": null}, {"id": 2, "sku": "INK-07", "price": 1.5, "discount": 0.1}]
from typing import Any, NotRequired, Optional, TypedDict

class Product(TypedDict):
  id: int
  sku: str
  price: float
  note: NotRequired[Optional[Any]]
  discount: NotRequired[float]

price 一个是 2、一个是 1.5,PEP 484 允许 int 当作 float 使用,所以字段是 float。运行时 Product.required_keys 为 {'id', 'sku', 'price'},optional_keys 为 {'note', 'discount'}(Python 3.12 实测)。

限制

  • null 会变成 Optional[Any],请把 Any 换成真实类型。
  • 不是合法 Python 标识符的键(如 user-id,或 class 这样的关键字)需要改名,Pydantic 里再配 Field(alias="user-id")。
  • 日期保持为 str;把类型改成 datetime 后,Pydantic 会解析 ISO 8601 字符串。
  • 根节点是基础类型数组时不生成类。

空数组与样本覆盖

空数组没有提供元素类型的依据,因此 {"tags": []} 会生成 tags: List[Any]。在同一输入数组中加入另一个含 {"tags": ["admin"]} 的对象,合并后的字段就变为 List[str]。生成器依据你提供的样本推断类型,无法推断所有样本中都未出现的字段。复制类定义前,请加入具有缺失键和 null 值的代表性对象。

FAQ

这个工具生成什么?

从 JSON 生成 Python 类定义,可选标准 @dataclass(stdlib)、Pydantic v2 BaseModel 或 TypedDict。每个嵌套对象都会成为独立的命名类。

支持哪些输出模式?

三种模式:@dataclass(Python 标准库,默认)、Pydantic v2 BaseModel、TypedDict(Python 3.8+;用到 NotRequired 时需 3.11+ 或 typing_extensions)。

JSON 类型如何映射到 Python 类型?

string→str、integer→int、float→float、boolean→bool、null→Optional[Any]、array→List[T]、嵌套对象→独立类。

何时字段标记为 Optional?

当 JSON 样本中字段值为 null,或在合并数组对象时某些对象中字段缺失,该字段被标记为 Optional[T] = None。

嵌套对象如何处理?

每个嵌套对象提取为独立类,类名由字段名转换为 PascalCase。子类始终在父类之前定义,输出可直接使用。

我的数据会发送到服务器吗?

不会。整个转换在浏览器中运行,数据不会离开本机。