Skip to content

Commit 0bc9109

Browse files
committed
feat: Add Pydantic model support for TOON conversion
- Add encode_pydantic() to convert Pydantic models to TOON format - Add decode_to_pydantic() to convert TOON back to Pydantic models - Support both Pydantic v1 and v2 - Add options for exclude_unset, exclude_none, exclude_defaults, by_alias - Fix decoder to handle top-level arrays correctly - Add comprehensive tests for Pydantic integration - Add pydantic usage examples - Update README.md and README.zh-CN.md with Pydantic documentation - Add pydantic as optional dependency in pyproject.toml
1 parent f3ccd1c commit 0bc9109

8 files changed

Lines changed: 1018 additions & 2 deletions

File tree

README.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ For development:
4040
pip install toonify[dev]
4141
```
4242

43+
With Pydantic support:
44+
```bash
45+
pip install toonify[pydantic]
46+
```
47+
4348
## Quick Start
4449

4550
### Python API
@@ -83,6 +88,48 @@ cat data.json | toon -e > data.toon
8388
toon data.json --stats
8489
```
8590

91+
### Pydantic Integration
92+
93+
TOON supports direct conversion from Pydantic models:
94+
95+
```python
96+
from pydantic import BaseModel
97+
from toon import encode_pydantic, decode_to_pydantic
98+
99+
# Define Pydantic models
100+
class User(BaseModel):
101+
id: int
102+
name: str
103+
email: str
104+
105+
# Encode Pydantic models to TOON
106+
users = [
107+
User(id=1, name='Alice', email='alice@example.com'),
108+
User(id=2, name='Bob', email='bob@example.com')
109+
]
110+
111+
toon = encode_pydantic(users)
112+
print(toon)
113+
# Output:
114+
# [2]{id,name,email}:
115+
# 1,Alice,alice@example.com
116+
# 2,Bob,bob@example.com
117+
118+
# Decode TOON back to Pydantic models
119+
decoded_users = decode_to_pydantic(toon, User)
120+
assert all(isinstance(u, User) for u in decoded_users)
121+
```
122+
123+
**Features:**
124+
- ✅ Direct conversion from Pydantic models (v1 and v2)
125+
- ✅ Support for nested models
126+
- ✅ Exclude unset, None, or default values
127+
- ✅ Field aliases support
128+
- ✅ Full validation on decode
129+
- ✅ Round-trip conversion
130+
131+
See [examples/pydantic_usage.py](examples/pydantic_usage.py) for more examples.
132+
86133
## TOON Format Specification
87134

88135
### Basic Syntax
@@ -184,6 +231,57 @@ data = decode(toon_string, {
184231
})
185232
```
186233

234+
### `encode_pydantic(model, options=None, exclude_unset=False, exclude_none=False, exclude_defaults=False, by_alias=False)`
235+
236+
Convert Pydantic model(s) to TOON string.
237+
238+
**Parameters:**
239+
- `model`: Pydantic model instance or list of model instances
240+
- `options`: Same as `encode()` function
241+
- `exclude_unset`: If True, exclude fields that were not explicitly set
242+
- `exclude_none`: If True, exclude fields with None values
243+
- `exclude_defaults`: If True, exclude fields with default values
244+
- `by_alias`: If True, use field aliases instead of field names
245+
246+
**Example:**
247+
```python
248+
from pydantic import BaseModel
249+
from toon import encode_pydantic
250+
251+
class User(BaseModel):
252+
id: int
253+
name: str
254+
email: str | None = None
255+
256+
user = User(id=1, name='Alice')
257+
toon = encode_pydantic(user, exclude_none=True)
258+
```
259+
260+
### `decode_to_pydantic(toon_string, model_class, options=None)`
261+
262+
Decode TOON string to Pydantic model(s).
263+
264+
**Parameters:**
265+
- `toon_string`: TOON formatted string
266+
- `model_class`: Pydantic model class to instantiate
267+
- `options`: Same as `decode()` function
268+
269+
**Returns:**
270+
- Pydantic model instance or list of instances (depending on input)
271+
272+
**Example:**
273+
```python
274+
from pydantic import BaseModel
275+
from toon import decode_to_pydantic
276+
277+
class User(BaseModel):
278+
id: int
279+
name: str
280+
281+
toon = "id: 1\nname: Alice"
282+
user = decode_to_pydantic(toon, User)
283+
```
284+
187285
## CLI Usage
188286

189287
```

README.zh-CN.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ pip install toonify
3636
pip install toonify[dev]
3737
```
3838

39+
支持Pydantic:
40+
```bash
41+
pip install toonify[pydantic]
42+
```
43+
3944
## 快速开始
4045

4146
### Python API
@@ -79,6 +84,48 @@ cat data.json | toon -e > data.toon
7984
toon data.json --stats
8085
```
8186

87+
### Pydantic集成
88+
89+
TOON支持直接从Pydantic模型转换:
90+
91+
```python
92+
from pydantic import BaseModel
93+
from toon import encode_pydantic, decode_to_pydantic
94+
95+
# 定义Pydantic模型
96+
class User(BaseModel):
97+
id: int
98+
name: str
99+
email: str
100+
101+
# 将Pydantic模型编码为TOON
102+
users = [
103+
User(id=1, name='Alice', email='alice@example.com'),
104+
User(id=2, name='Bob', email='bob@example.com')
105+
]
106+
107+
toon = encode_pydantic(users)
108+
print(toon)
109+
# 输出:
110+
# [2]{id,name,email}:
111+
# 1,Alice,alice@example.com
112+
# 2,Bob,bob@example.com
113+
114+
# 将TOON解码回Pydantic模型
115+
decoded_users = decode_to_pydantic(toon, User)
116+
assert all(isinstance(u, User) for u in decoded_users)
117+
```
118+
119+
**特性:**
120+
- ✅ 直接从Pydantic模型转换(支持v1和v2)
121+
- ✅ 支持嵌套模型
122+
- ✅ 排除未设置、None或默认值
123+
- ✅ 支持字段别名
124+
- ✅ 解码时完全验证
125+
- ✅ 往返转换
126+
127+
详见[examples/pydantic_usage.py](examples/pydantic_usage.py)
128+
82129
## TOON格式规范
83130

84131
### 基本语法
@@ -180,6 +227,57 @@ data = decode(toon_string, {
180227
})
181228
```
182229

230+
### `encode_pydantic(model, options=None, exclude_unset=False, exclude_none=False, exclude_defaults=False, by_alias=False)`
231+
232+
将Pydantic模型转换为TOON字符串。
233+
234+
**参数:**
235+
- `model`:Pydantic模型实例或模型实例列表
236+
- `options`:与`encode()`函数相同
237+
- `exclude_unset`:如果为True,排除未明确设置的字段
238+
- `exclude_none`:如果为True,排除None值字段
239+
- `exclude_defaults`:如果为True,排除具有默认值的字段
240+
- `by_alias`:如果为True,使用字段别名而不是字段名称
241+
242+
**示例:**
243+
```python
244+
from pydantic import BaseModel
245+
from toon import encode_pydantic
246+
247+
class User(BaseModel):
248+
id: int
249+
name: str
250+
email: str | None = None
251+
252+
user = User(id=1, name='Alice')
253+
toon = encode_pydantic(user, exclude_none=True)
254+
```
255+
256+
### `decode_to_pydantic(toon_string, model_class, options=None)`
257+
258+
将TOON字符串解码为Pydantic模型。
259+
260+
**参数:**
261+
- `toon_string`:TOON格式字符串
262+
- `model_class`:要实例化的Pydantic模型类
263+
- `options`:与`decode()`函数相同
264+
265+
**返回:**
266+
- Pydantic模型实例或实例列表(取决于输入)
267+
268+
**示例:**
269+
```python
270+
from pydantic import BaseModel
271+
from toon import decode_to_pydantic
272+
273+
class User(BaseModel):
274+
id: int
275+
name: str
276+
277+
toon = "id: 1\nname: Alice"
278+
user = decode_to_pydantic(toon, User)
279+
```
280+
183281
## CLI使用
184282

185283
```

0 commit comments

Comments
 (0)