or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-responses.mdapi-routing.mdbackground-tasks.mdcore-application.mddata-utilities.mddependency-injection.mdexception-handling.mdindex.mdmiddleware.mdrequest-parameters.mdrequest-response.mdsecurity-authentication.mdstatic-templating.mdtesting.mdwebsocket-support.md

data-utilities.mddocs/

0

# Data Utilities

1

2

FastAPI provides utility functions for data encoding and serialization, particularly useful for converting Python objects to JSON-compatible formats. These utilities are essential for handling complex data types that aren't natively JSON serializable, such as datetime objects, Pydantic models, and database models.

3

4

## Capabilities

5

6

### JSON Encodable Converter

7

8

Primary utility function for converting Python objects to JSON-compatible formats with extensive customization options.

9

10

```python { .api }

11

def jsonable_encoder(

12

obj: Any,

13

include: Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any]] = None,

14

exclude: Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any]] = None,

15

by_alias: bool = True,

16

exclude_unset: bool = False,

17

exclude_defaults: bool = False,

18

exclude_none: bool = False,

19

round_trip: bool = True,

20

timedelta_isoformat: str = "iso8601",

21

sqlalchemy_safe: bool = True,

22

fallback: Callable[[Any], Any] = None,

23

) -> Any:

24

"""

25

Convert any object to a JSON-compatible format.

26

27

Parameters:

28

- obj: The object to encode

29

- include: Fields to include (set of field names or dict with nested structure)

30

- exclude: Fields to exclude (set of field names or dict with nested structure)

31

- by_alias: Use field aliases if available (Pydantic models)

32

- exclude_unset: Exclude fields that weren't explicitly set

33

- exclude_defaults: Exclude fields that contain their default value

34

- exclude_none: Exclude fields with None values

35

- round_trip: Enable round-trip serialization compatibility

36

- timedelta_isoformat: Format for timedelta objects ("iso8601" or "float")

37

- sqlalchemy_safe: Safe handling of SQLAlchemy models

38

- fallback: Custom fallback function for unsupported types

39

40

Returns:

41

JSON-compatible object (dict, list, str, int, float, bool, None)

42

"""

43

```

44

45

## Usage Examples

46

47

### Basic Object Encoding

48

49

```python

50

from fastapi.encoders import jsonable_encoder

51

from datetime import datetime, date, timedelta

52

from decimal import Decimal

53

from uuid import UUID, uuid4

54

55

# Basic Python types

56

data = {

57

"string": "hello",

58

"integer": 42,

59

"float": 3.14,

60

"boolean": True,

61

"none": None,

62

"list": [1, 2, 3],

63

"dict": {"nested": "value"}

64

}

65

66

encoded = jsonable_encoder(data)

67

print(encoded) # Already JSON-compatible, returned as-is

68

69

# Complex types that need encoding

70

complex_data = {

71

"datetime": datetime.now(),

72

"date": date.today(),

73

"timedelta": timedelta(hours=2, minutes=30),

74

"decimal": Decimal("10.50"),

75

"uuid": uuid4(),

76

"bytes": b"binary data",

77

"set": {1, 2, 3}

78

}

79

80

encoded_complex = jsonable_encoder(complex_data)

81

print(encoded_complex)

82

# {

83

# "datetime": "2024-01-15T10:30:00.123456",

84

# "date": "2024-01-15",

85

# "timedelta": "PT2H30M",

86

# "decimal": 10.5,

87

# "uuid": "123e4567-e89b-12d3-a456-426614174000",

88

# "bytes": "YmluYXJ5IGRhdGE=", # base64 encoded

89

# "set": [1, 2, 3]

90

# }

91

```

92

93

### Pydantic Model Encoding

94

95

```python

96

from fastapi.encoders import jsonable_encoder

97

from pydantic import BaseModel, Field

98

from typing import Optional

99

from datetime import datetime

100

101

class User(BaseModel):

102

id: int

103

name: str

104

email: str

105

full_name: Optional[str] = Field(None, alias="fullName")

106

created_at: datetime

107

is_active: bool = True

108

109

class UserProfile(BaseModel):

110

user: User

111

preferences: dict

112

login_count: int = 0

113

114

# Create model instances

115

user = User(

116

id=1,

117

name="john_doe",

118

email="john@example.com",

119

fullName="John Doe",

120

created_at=datetime.now()

121

)

122

123

profile = UserProfile(

124

user=user,

125

preferences={"theme": "dark", "notifications": True}

126

)

127

128

# Encode with default settings

129

encoded = jsonable_encoder(profile)

130

print(encoded)

131

132

# Encode using aliases

133

encoded_with_aliases = jsonable_encoder(profile, by_alias=True)

134

print(encoded_with_aliases["user"]["fullName"]) # Uses alias

135

136

# Exclude certain fields

137

encoded_minimal = jsonable_encoder(

138

profile,

139

exclude={"user": {"created_at"}, "login_count"}

140

)

141

142

# Include only specific fields

143

encoded_specific = jsonable_encoder(

144

profile,

145

include={"user": {"id", "name"}, "preferences"}

146

)

147

148

# Exclude unset fields

149

user_partial = User(id=2, name="jane", email="jane@example.com")

150

encoded_no_unset = jsonable_encoder(user_partial, exclude_unset=True)

151

# Won't include created_at if it wasn't explicitly set

152

153

# Exclude None values

154

user_with_none = User(

155

id=3,

156

name="bob",

157

email="bob@example.com",

158

full_name=None, # Explicitly set to None

159

created_at=datetime.now()

160

)

161

encoded_no_none = jsonable_encoder(user_with_none, exclude_none=True)

162

```

163

164

### Database Model Integration

165

166

```python

167

from fastapi import FastAPI, Depends

168

from fastapi.encoders import jsonable_encoder

169

from sqlalchemy.orm import Session

170

# Assuming SQLAlchemy models

171

172

app = FastAPI()

173

174

@app.get("/users/{user_id}")

175

def get_user(user_id: int, db: Session = Depends(get_db)):

176

user = db.query(UserModel).filter(UserModel.id == user_id).first()

177

178

if not user:

179

raise HTTPException(status_code=404, detail="User not found")

180

181

# Convert SQLAlchemy model to JSON-compatible dict

182

user_data = jsonable_encoder(user, sqlalchemy_safe=True)

183

return user_data

184

185

@app.get("/users/{user_id}/profile")

186

def get_user_profile(user_id: int, db: Session = Depends(get_db)):

187

user = db.query(UserModel).filter(UserModel.id == user_id).first()

188

189

if not user:

190

raise HTTPException(status_code=404, detail="User not found")

191

192

# Include related data, exclude sensitive fields

193

profile_data = jsonable_encoder(

194

user,

195

include={

196

"id", "name", "email", "created_at", "last_login",

197

"profile": {"bio", "location", "website"},

198

"posts": {"id", "title", "created_at"}

199

},

200

exclude={"password_hash", "email_verified_token"}

201

)

202

return profile_data

203

```

204

205

### Custom Fallback Function

206

207

```python

208

from fastapi.encoders import jsonable_encoder

209

import numpy as np

210

from typing import Any

211

212

# Custom fallback for handling NumPy arrays

213

def numpy_fallback(obj: Any) -> Any:

214

if isinstance(obj, np.ndarray):

215

return obj.tolist()

216

elif isinstance(obj, np.integer):

217

return int(obj)

218

elif isinstance(obj, np.floating):

219

return float(obj)

220

else:

221

# Re-raise the TypeError to use default handling

222

raise TypeError(f"Object of type {type(obj)} is not JSON serializable")

223

224

# Data with NumPy objects

225

data_with_numpy = {

226

"array": np.array([1, 2, 3, 4]),

227

"matrix": np.array([[1, 2], [3, 4]]),

228

"int64": np.int64(42),

229

"float64": np.float64(3.14159)

230

}

231

232

encoded_numpy = jsonable_encoder(data_with_numpy, fallback=numpy_fallback)

233

print(encoded_numpy)

234

# {

235

# "array": [1, 2, 3, 4],

236

# "matrix": [[1, 2], [3, 4]],

237

# "int64": 42,

238

# "float64": 3.14159

239

# }

240

```

241

242

### Response Encoding in Endpoints

243

244

```python

245

from fastapi import FastAPI, HTTPException

246

from fastapi.encoders import jsonable_encoder

247

from fastapi.responses import JSONResponse

248

249

app = FastAPI()

250

251

@app.get("/complex-data")

252

def get_complex_data():

253

complex_response = {

254

"timestamp": datetime.now(),

255

"data": {

256

"measurements": [

257

{"value": Decimal("123.456"), "unit": "kg"},

258

{"value": Decimal("789.012"), "unit": "kg"}

259

],

260

"metadata": {

261

"id": uuid4(),

262

"processed": True

263

}

264

}

265

}

266

267

# Encode the complex data structure

268

encoded_response = jsonable_encoder(complex_response)

269

return JSONResponse(content=encoded_response)

270

271

@app.post("/process-data")

272

def process_data(raw_data: dict):

273

# Process and potentially modify data

274

processed = {

275

"original": raw_data,

276

"processed_at": datetime.now(),

277

"result": calculate_result(raw_data),

278

"metadata": {

279

"version": "1.0",

280

"processor_id": uuid4()

281

}

282

}

283

284

# Use jsonable_encoder to ensure everything is JSON-compatible

285

return jsonable_encoder(processed, exclude_none=True)

286

```

287

288

### Time Delta Formatting Options

289

290

```python

291

from fastapi.encoders import jsonable_encoder

292

from datetime import timedelta

293

294

duration_data = {

295

"short": timedelta(minutes=30),

296

"medium": timedelta(hours=2, minutes=45),

297

"long": timedelta(days=5, hours=3, minutes=20)

298

}

299

300

# ISO 8601 format (default)

301

iso_encoded = jsonable_encoder(duration_data, timedelta_isoformat="iso8601")

302

print(iso_encoded)

303

# {

304

# "short": "PT30M",

305

# "medium": "PT2H45M",

306

# "long": "P5DT3H20M"

307

# }

308

309

# Float format (total seconds)

310

float_encoded = jsonable_encoder(duration_data, timedelta_isoformat="float")

311

print(float_encoded)

312

# {

313

# "short": 1800.0,

314

# "medium": 9900.0,

315

# "long": 443400.0

316

# }

317

```

318

319

## Types

320

321

```python { .api }

322

from typing import Any, Callable, Dict, List, Optional, Set, Union

323

324

# Include/exclude type for field selection

325

IncEx = Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any], None]

326

327

# Fallback function type

328

FallbackFunc = Callable[[Any], Any]

329

330

# Supported timedelta formats

331

TimedeltaIsoFormat = Union["iso8601", "float"]

332

```