or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

blueprints.mdcli.mdconfiguration.mdcontext-globals.mdcore-application.mdhelpers.mdindex.mdjson-support.mdrequest-response.mdrouting.mdsessions.mdsignals.mdtemplates.mdtesting.md

json-support.mddocs/

0

# JSON Support

1

2

Flask provides comprehensive JSON handling capabilities through the `flask.json` module, including serialization, deserialization, and response creation with Flask-specific enhancements.

3

4

## Capabilities

5

6

### JSON Response Creation

7

8

Function for creating JSON responses with proper headers and formatting.

9

10

```python { .api }

11

def jsonify(*args, **kwargs) -> Response:

12

"""

13

Create a JSON response from arguments.

14

15

Args:

16

*args: Positional arguments (single value or multiple values as array)

17

**kwargs: Keyword arguments (treated as object properties)

18

19

Returns:

20

Response object with JSON content and application/json mimetype

21

22

Examples:

23

jsonify(message="Hello")

24

jsonify([1, 2, 3])

25

jsonify({"key": "value"})

26

jsonify(users=[{"name": "John"}, {"name": "Jane"}])

27

"""

28

```

29

30

### JSON Serialization

31

32

Functions for converting Python objects to JSON strings.

33

34

```python { .api }

35

def dumps(obj: Any, **kwargs) -> str:

36

"""

37

Serialize object to JSON string.

38

39

Args:

40

obj: Object to serialize

41

**kwargs: Arguments passed to JSON encoder

42

43

Returns:

44

JSON string

45

46

Note:

47

Uses current app's JSON provider if available, otherwise standard json.dumps

48

"""

49

50

def dump(obj: Any, fp: IO[str], **kwargs) -> None:

51

"""

52

Serialize object to JSON and write to file.

53

54

Args:

55

obj: Object to serialize

56

fp: File-like object to write to

57

**kwargs: Arguments passed to JSON encoder

58

59

Note:

60

Uses current app's JSON provider if available, otherwise standard json.dump

61

"""

62

```

63

64

### JSON Deserialization

65

66

Functions for parsing JSON strings into Python objects.

67

68

```python { .api }

69

def loads(s: str | bytes, **kwargs) -> Any:

70

"""

71

Deserialize JSON string to Python object.

72

73

Args:

74

s: JSON string or bytes

75

**kwargs: Arguments passed to JSON decoder

76

77

Returns:

78

Deserialized Python object

79

80

Note:

81

Uses current app's JSON provider if available, otherwise standard json.loads

82

"""

83

84

def load(fp: IO[AnyStr], **kwargs) -> Any:

85

"""

86

Deserialize JSON from file to Python object.

87

88

Args:

89

fp: File-like object to read from

90

**kwargs: Arguments passed to JSON decoder

91

92

Returns:

93

Deserialized Python object

94

95

Note:

96

Uses current app's JSON provider if available, otherwise standard json.load

97

"""

98

```

99

100

### JSON Provider System

101

102

Classes for customizing JSON behavior in Flask applications.

103

104

```python { .api }

105

class JSONProvider:

106

"""Base class for JSON providers."""

107

108

def dumps(self, obj: Any, **kwargs) -> str:

109

"""Serialize object to JSON string."""

110

111

def loads(self, s: str | bytes, **kwargs) -> Any:

112

"""Deserialize JSON string to object."""

113

114

def dump(self, obj: Any, fp: IO[str], **kwargs) -> None:

115

"""Serialize object to JSON file."""

116

117

def load(self, fp: IO[AnyStr], **kwargs) -> Any:

118

"""Deserialize JSON from file."""

119

120

def response(self, *args, **kwargs) -> Response:

121

"""Create JSON response."""

122

123

class DefaultJSONProvider(JSONProvider):

124

"""Default JSON provider with Flask-specific enhancements."""

125

126

def __init__(self, app: Flask) -> None:

127

"""Initialize provider for Flask app."""

128

129

default: Callable[[Any], Any] | None # Default function for non-serializable objects

130

ensure_ascii: bool # Ensure ASCII output

131

sort_keys: bool # Sort object keys

132

compact: bool | None # Compact output format

133

mimetype: str # Response mimetype

134

```

135

136

### JSON Tag System

137

138

Classes for handling complex object serialization with tags.

139

140

```python { .api }

141

class JSONTag:

142

"""Base class for JSON object tags."""

143

144

key: str # Tag key identifier

145

146

def check(self, value: Any) -> bool:

147

"""Check if value should use this tag."""

148

149

def to_json(self, value: Any) -> Any:

150

"""Convert value to JSON-serializable form."""

151

152

def to_python(self, value: Any) -> Any:

153

"""Convert JSON value back to Python object."""

154

155

class TaggedJSONSerializer:

156

"""Serializer that handles tagged objects."""

157

158

def __init__(self) -> None:

159

"""Initialize serializer."""

160

161

def register(self, tag_class: type[JSONTag], force: bool = False, index: int | None = None) -> None:

162

"""Register a tag class."""

163

164

def tag(self, value: Any) -> dict[str, Any]:

165

"""Tag a value for serialization."""

166

167

def untag(self, value: dict[str, Any]) -> Any:

168

"""Untag a value during deserialization."""

169

170

def dumps(self, value: Any, **kwargs) -> str:

171

"""Serialize with tagging."""

172

173

def loads(self, value: str, **kwargs) -> Any:

174

"""Deserialize with untagging."""

175

```

176

177

## Usage Examples

178

179

### Basic JSON Responses

180

181

```python

182

from flask import Flask, jsonify, request

183

184

app = Flask(__name__)

185

186

@app.route('/api/user/<int:user_id>')

187

def get_user(user_id):

188

# Simple JSON response

189

user = {

190

'id': user_id,

191

'name': f'User {user_id}',

192

'email': f'user{user_id}@example.com'

193

}

194

return jsonify(user)

195

196

@app.route('/api/users')

197

def get_users():

198

# JSON array response

199

users = [

200

{'id': 1, 'name': 'John'},

201

{'id': 2, 'name': 'Jane'},

202

{'id': 3, 'name': 'Bob'}

203

]

204

return jsonify(users)

205

206

@app.route('/api/status')

207

def status():

208

# JSON with multiple keys

209

return jsonify(

210

status='ok',

211

version='1.0',

212

timestamp='2023-01-01T00:00:00Z'

213

)

214

215

@app.route('/api/message')

216

def message():

217

# Simple message

218

return jsonify(message='Hello, World!')

219

```

220

221

### JSON Request Handling

222

223

```python

224

from flask import Flask, request, jsonify

225

import json

226

227

app = Flask(__name__)

228

229

@app.route('/api/users', methods=['POST'])

230

def create_user():

231

# Get JSON data from request

232

if not request.is_json:

233

return jsonify(error='Content-Type must be application/json'), 400

234

235

data = request.get_json()

236

237

# Validate required fields

238

required_fields = ['name', 'email']

239

for field in required_fields:

240

if field not in data:

241

return jsonify(error=f'Missing field: {field}'), 400

242

243

# Create user (simulate)

244

user = {

245

'id': 123,

246

'name': data['name'],

247

'email': data['email'],

248

'created': '2023-01-01T00:00:00Z'

249

}

250

251

return jsonify(user), 201

252

253

@app.route('/api/bulk-upload', methods=['POST'])

254

def bulk_upload():

255

try:

256

data = request.get_json(force=True)

257

except Exception as e:

258

return jsonify(error='Invalid JSON'), 400

259

260

if not isinstance(data, list):

261

return jsonify(error='Expected JSON array'), 400

262

263

results = []

264

for item in data:

265

# Process each item

266

results.append({

267

'id': item.get('id'),

268

'status': 'processed'

269

})

270

271

return jsonify(results=results, count=len(results))

272

```

273

274

### Custom JSON Serialization

275

276

```python

277

from flask import Flask, jsonify

278

from datetime import datetime, date

279

from decimal import Decimal

280

import uuid

281

282

app = Flask(__name__)

283

284

# Custom JSON encoder for special types

285

def custom_json_default(obj):

286

"""Custom JSON serialization for unsupported types."""

287

if isinstance(obj, datetime):

288

return obj.isoformat()

289

elif isinstance(obj, date):

290

return obj.isoformat()

291

elif isinstance(obj, Decimal):

292

return float(obj)

293

elif isinstance(obj, uuid.UUID):

294

return str(obj)

295

elif hasattr(obj, 'to_dict'):

296

return obj.to_dict()

297

298

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

299

300

# Configure the app's JSON provider

301

app.json.default = custom_json_default

302

303

class User:

304

def __init__(self, id, name, created):

305

self.id = id

306

self.name = name

307

self.created = created

308

309

def to_dict(self):

310

return {

311

'id': self.id,

312

'name': self.name,

313

'created': self.created

314

}

315

316

@app.route('/api/advanced')

317

def advanced_json():

318

data = {

319

'timestamp': datetime.now(),

320

'date': date.today(),

321

'price': Decimal('19.99'),

322

'uuid': uuid.uuid4(),

323

'user': User(1, 'John', datetime.now())

324

}

325

326

return jsonify(data)

327

```

328

329

### JSON Configuration

330

331

```python

332

from flask import Flask, jsonify

333

334

app = Flask(__name__)

335

336

# Configure JSON behavior

337

app.json.ensure_ascii = False # Allow Unicode characters

338

app.json.sort_keys = True # Sort object keys

339

app.json.compact = True # Use compact representation

340

341

@app.route('/api/unicode')

342

def unicode_response():

343

return jsonify(

344

message='Hello, 世界! 🌍',

345

emoji='🚀',

346

chinese='你好'

347

)

348

349

@app.route('/api/pretty')

350

def pretty_json():

351

# Override compact setting for this response

352

data = {

353

'users': [

354

{'name': 'Alice', 'age': 30},

355

{'name': 'Bob', 'age': 25}

356

],

357

'meta': {

358

'total': 2,

359

'page': 1

360

}

361

}

362

363

# Create pretty-printed JSON

364

import json

365

pretty_json = json.dumps(data, indent=2, sort_keys=True)

366

367

from flask import Response

368

return Response(

369

pretty_json,

370

mimetype='application/json'

371

)

372

```

373

374

### Error Handling with JSON

375

376

```python

377

from flask import Flask, jsonify, request

378

import logging

379

380

app = Flask(__name__)

381

382

@app.errorhandler(400)

383

def bad_request(error):

384

return jsonify(

385

error='Bad Request',

386

message=str(error),

387

status_code=400

388

), 400

389

390

@app.errorhandler(404)

391

def not_found(error):

392

return jsonify(

393

error='Not Found',

394

message='The requested resource was not found',

395

status_code=404

396

), 404

397

398

@app.errorhandler(500)

399

def internal_error(error):

400

app.logger.error(f'Server Error: {error}')

401

return jsonify(

402

error='Internal Server Error',

403

message='An unexpected error occurred',

404

status_code=500

405

), 500

406

407

@app.route('/api/error-test')

408

def error_test():

409

error_type = request.args.get('type', 'none')

410

411

if error_type == '400':

412

from flask import abort

413

abort(400, description="Test bad request")

414

elif error_type == '404':

415

abort(404)

416

elif error_type == '500':

417

raise Exception("Test internal error")

418

419

return jsonify(message='No error')

420

```

421

422

### Streaming JSON

423

424

```python

425

from flask import Flask, Response, stream_with_context

426

import json

427

import time

428

429

app = Flask(__name__)

430

431

@app.route('/api/stream')

432

def stream_json():

433

def generate_data():

434

yield '{"items": ['

435

436

for i in range(100):

437

if i > 0:

438

yield ','

439

440

item = {

441

'id': i,

442

'name': f'Item {i}',

443

'timestamp': time.time()

444

}

445

446

yield json.dumps(item)

447

time.sleep(0.1) # Simulate processing

448

449

yield ']}'

450

451

return Response(

452

stream_with_context(generate_data()),

453

mimetype='application/json'

454

)

455

456

@app.route('/api/json-lines')

457

def json_lines():

458

"""Stream JSON Lines format (one JSON object per line)."""

459

def generate_lines():

460

for i in range(50):

461

item = {

462

'id': i,

463

'data': f'Record {i}',

464

'processed_at': time.time()

465

}

466

yield json.dumps(item) + '\n'

467

time.sleep(0.2)

468

469

return Response(

470

stream_with_context(generate_lines()),

471

mimetype='application/x-ndjson'

472

)

473

```

474

475

### Custom JSON Provider

476

477

```python

478

from flask import Flask

479

from flask.json.provider import DefaultJSONProvider

480

import orjson # Fast JSON library

481

482

class OrjsonProvider(DefaultJSONProvider):

483

"""Custom JSON provider using orjson for better performance."""

484

485

def dumps(self, obj, **kwargs):

486

# orjson returns bytes, so decode to string

487

return orjson.dumps(obj).decode('utf-8')

488

489

def loads(self, s, **kwargs):

490

return orjson.loads(s)

491

492

app = Flask(__name__)

493

app.json = OrjsonProvider(app)

494

495

@app.route('/api/fast')

496

def fast_json():

497

# Large data structure

498

data = {

499

'items': [{'id': i, 'value': f'item_{i}'} for i in range(1000)]

500

}

501

502

from flask import jsonify

503

return jsonify(data)

504

```

505

506

### JSON Schema Validation

507

508

```python

509

from flask import Flask, request, jsonify

510

import jsonschema

511

from jsonschema import validate, ValidationError

512

513

app = Flask(__name__)

514

515

# Define JSON schemas

516

USER_SCHEMA = {

517

"type": "object",

518

"properties": {

519

"name": {"type": "string", "minLength": 1},

520

"email": {"type": "string", "format": "email"},

521

"age": {"type": "integer", "minimum": 0, "maximum": 150}

522

},

523

"required": ["name", "email"],

524

"additionalProperties": False

525

}

526

527

def validate_json(schema):

528

"""Decorator to validate JSON against schema."""

529

def decorator(f):

530

def wrapper(*args, **kwargs):

531

try:

532

validate(request.get_json(), schema)

533

except ValidationError as e:

534

return jsonify(

535

error="Validation Error",

536

message=e.message,

537

path=list(e.path)

538

), 400

539

except Exception as e:

540

return jsonify(error="Invalid JSON"), 400

541

542

return f(*args, **kwargs)

543

544

wrapper.__name__ = f.__name__

545

return wrapper

546

return decorator

547

548

@app.route('/api/users', methods=['POST'])

549

@validate_json(USER_SCHEMA)

550

def create_user_validated():

551

data = request.get_json()

552

553

# Data is now guaranteed to be valid

554

user = {

555

'id': 123,

556

'name': data['name'],

557

'email': data['email'],

558

'age': data.get('age')

559

}

560

561

return jsonify(user), 201

562

```