or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

agent-sessions.mdauth-security.mdfile-uploads.mdhttp-methods.mdindex.mdparsers-serializers.mdrequest-building.mdrequest-execution.mdresponse-handling.md

parsers-serializers.mddocs/

0

# Parsers & Serializers

1

2

Configurable content-type parsing and serialization for different data formats, with built-in support for JSON, form data, text, and binary content, plus extensible custom parser system.

3

4

## Capabilities

5

6

### Global Serializers

7

8

Default serialization functions for converting request data to appropriate formats.

9

10

```javascript { .api }

11

/**

12

* Global serializer configuration object

13

*/

14

const serialize = {

15

'application/json': Function,

16

'application/x-www-form-urlencoded': Function

17

};

18

19

// Available serializers

20

serialize['application/json']: (obj: any) => string;

21

serialize['application/x-www-form-urlencoded']: (obj: object) => string;

22

```

23

24

**Usage Examples:**

25

26

```javascript

27

const superagent = require('superagent');

28

29

// JSON serialization (automatic)

30

superagent

31

.post('https://api.example.com/users')

32

.send({ name: 'John', age: 30 });

33

// Automatically uses serialize['application/json']

34

35

// Form serialization (automatic)

36

superagent

37

.post('https://api.example.com/form')

38

.type('form')

39

.send({ username: 'user', password: 'pass' });

40

// Automatically uses serialize['application/x-www-form-urlencoded']

41

42

// Access global serializers

43

console.log('JSON serializer:', superagent.serialize['application/json']);

44

console.log('Form serializer:', superagent.serialize['application/x-www-form-urlencoded']);

45

46

// Custom global serializer

47

superagent.serialize['application/xml'] = (obj) => {

48

// Custom XML serialization logic

49

return `<data>${JSON.stringify(obj)}</data>`;

50

};

51

```

52

53

### Global Parsers

54

55

Default parsing functions for converting response data from various formats.

56

57

```javascript { .api }

58

/**

59

* Global parser configuration object

60

*/

61

const parse = {

62

'application/json': Function,

63

'application/x-www-form-urlencoded': Function,

64

'text/plain': Function,

65

'text/*': Function,

66

'application/octet-stream': Function,

67

'image/*': Function

68

};

69

70

// Available parsers

71

parse['application/json']: (res: Response, callback: Function) => void;

72

parse['application/x-www-form-urlencoded']: (res: Response, callback: Function) => void;

73

parse['text/plain']: (res: Response, callback: Function) => void;

74

parse.text: (res: Response, callback: Function) => void;

75

parse.image: (res: Response, callback: Function) => void;

76

```

77

78

**Usage Examples:**

79

80

```javascript

81

// JSON parsing (automatic)

82

const jsonResponse = await superagent.get('https://api.example.com/data.json');

83

console.log('Parsed JSON:', jsonResponse.body);

84

85

// Text parsing (automatic)

86

const textResponse = await superagent.get('https://api.example.com/plain.txt');

87

console.log('Text content:', textResponse.text);

88

89

// Binary/Image parsing (automatic)

90

const imageResponse = await superagent.get('https://api.example.com/image.jpg');

91

console.log('Binary buffer:', imageResponse.body instanceof Buffer);

92

93

// Access global parsers

94

console.log('JSON parser:', superagent.parse['application/json']);

95

console.log('Text parser:', superagent.parse.text);

96

console.log('Image parser:', superagent.parse.image);

97

98

// Custom global parser

99

superagent.parse['application/xml'] = (res, callback) => {

100

// Custom XML parsing logic

101

const xmlData = parseXML(res.text);

102

callback(null, xmlData);

103

};

104

```

105

106

### Request-Level Serialization

107

108

Override serialization for individual requests.

109

110

```javascript { .api }

111

/**

112

* Override request serializer function

113

* @param {function} fn - Custom serializer function

114

* @returns {Request} Request instance for chaining

115

*/

116

Request.prototype.serialize(fn): Request;

117

```

118

119

**Usage Examples:**

120

121

```javascript

122

// Custom JSON serialization with pretty printing

123

superagent

124

.post('https://api.example.com/data')

125

.serialize((obj) => JSON.stringify(obj, null, 2))

126

.send({ message: 'Hello World' });

127

128

// Custom form serialization

129

superagent

130

.post('https://api.example.com/form')

131

.type('form')

132

.serialize((obj) => {

133

// Custom form encoding with special handling

134

return Object.keys(obj)

135

.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`)

136

.join('&');

137

})

138

.send({ special_chars: 'hello+world&test' });

139

140

// CSV serialization

141

superagent

142

.post('https://api.example.com/csv')

143

.type('text/csv')

144

.serialize((data) => {

145

// Convert array of objects to CSV

146

const headers = Object.keys(data[0]).join(',');

147

const rows = data.map(row => Object.values(row).join(','));

148

return [headers, ...rows].join('\n');

149

})

150

.send([

151

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

152

{ name: 'Jane', age: 25 }

153

]);

154

155

// XML serialization

156

superagent

157

.post('https://api.example.com/xml')

158

.type('application/xml')

159

.serialize((obj) => {

160

function objectToXml(obj, rootName = 'data') {

161

let xml = `<${rootName}>`;

162

for (const [key, value] of Object.entries(obj)) {

163

if (typeof value === 'object') {

164

xml += objectToXml(value, key);

165

} else {

166

xml += `<${key}>${value}</${key}>`;

167

}

168

}

169

xml += `</${rootName}>`;

170

return xml;

171

}

172

return objectToXml(obj);

173

})

174

.send({ user: { name: 'John', age: 30 } });

175

```

176

177

### Request-Level Parsing

178

179

Override parsing for individual requests.

180

181

```javascript { .api }

182

/**

183

* Override response parser function

184

* @param {function} fn - Custom parser function (res, callback) => void

185

* @returns {Request} Request instance for chaining

186

*/

187

Request.prototype.parse(fn): Request;

188

```

189

190

**Usage Examples:**

191

192

```javascript

193

// Custom JSON parser with error handling

194

superagent

195

.get('https://api.example.com/data')

196

.parse((res, callback) => {

197

try {

198

const data = JSON.parse(res.text);

199

callback(null, data);

200

} catch (err) {

201

callback(new Error('Invalid JSON: ' + err.message));

202

}

203

})

204

.end((err, res) => {

205

if (err) {

206

console.error('Parse error:', err.message);

207

} else {

208

console.log('Parsed data:', res.body);

209

}

210

});

211

212

// CSV parser

213

superagent

214

.get('https://api.example.com/data.csv')

215

.parse((res, callback) => {

216

const lines = res.text.split('\n');

217

const headers = lines[0].split(',');

218

const data = lines.slice(1).map(line => {

219

const values = line.split(',');

220

const obj = {};

221

headers.forEach((header, index) => {

222

obj[header.trim()] = values[index]?.trim();

223

});

224

return obj;

225

});

226

callback(null, data);

227

})

228

.end((err, res) => {

229

console.log('CSV data:', res.body);

230

});

231

232

// XML parser

233

superagent

234

.get('https://api.example.com/data.xml')

235

.parse((res, callback) => {

236

// Simple XML parsing (in practice, use a proper XML parser)

237

const xmlData = {};

238

const matches = res.text.match(/<(\w+)>([^<]+)<\/\1>/g);

239

if (matches) {

240

matches.forEach(match => {

241

const [, key, value] = match.match(/<(\w+)>([^<]+)<\/\1>/);

242

xmlData[key] = value;

243

});

244

}

245

callback(null, xmlData);

246

});

247

248

// Binary data parser with validation

249

superagent

250

.get('https://api.example.com/file.pdf')

251

.parse((res, callback) => {

252

const buffer = Buffer.from(res.body);

253

254

// Validate PDF header

255

if (buffer.slice(0, 4).toString() !== '%PDF') {

256

return callback(new Error('Invalid PDF file'));

257

}

258

259

callback(null, {

260

type: 'pdf',

261

size: buffer.length,

262

buffer: buffer

263

});

264

});

265

266

// Custom text parser with encoding detection

267

superagent

268

.get('https://api.example.com/text')

269

.parse((res, callback) => {

270

let text = res.text;

271

272

// Handle different encodings or formats

273

if (res.charset === 'iso-8859-1') {

274

// Convert from Latin-1 to UTF-8

275

text = Buffer.from(text, 'latin1').toString('utf8');

276

}

277

278

// Additional text processing

279

const processedText = text

280

.replace(/\r\n/g, '\n') // Normalize line endings

281

.trim(); // Remove whitespace

282

283

callback(null, processedText);

284

});

285

```

286

287

### Content-Type Detection

288

289

Automatic parser selection based on response content type.

290

291

```javascript

292

// Automatic parser selection examples

293

294

// JSON response - uses parse['application/json']

295

const jsonResponse = await superagent.get('https://api.example.com/users');

296

// Content-Type: application/json

297

console.log(typeof jsonResponse.body); // 'object'

298

299

// Text response - uses parse.text

300

const textResponse = await superagent.get('https://api.example.com/readme.txt');

301

// Content-Type: text/plain

302

console.log(typeof textResponse.body); // 'string'

303

304

// Binary response - uses parse.image

305

const binaryResponse = await superagent.get('https://api.example.com/file.pdf');

306

// Content-Type: application/pdf

307

console.log(binaryResponse.body instanceof Buffer); // true

308

309

// Form response - uses parse['application/x-www-form-urlencoded']

310

const formResponse = await superagent.get('https://api.example.com/form-data');

311

// Content-Type: application/x-www-form-urlencoded

312

console.log(typeof formResponse.body); // 'object'

313

```

314

315

### Buffering Configuration

316

317

Configure response buffering behavior for different content types.

318

319

```javascript { .api }

320

/**

321

* Global buffer configuration object

322

*/

323

const buffer = {};

324

325

// Configure buffering for specific content types

326

buffer['application/json'] = boolean;

327

buffer['text/plain'] = boolean;

328

buffer['image/*'] = boolean;

329

```

330

331

**Usage Examples:**

332

333

```javascript

334

// Configure global buffering

335

superagent.buffer['application/json'] = true; // Buffer JSON responses

336

superagent.buffer['text/plain'] = true; // Buffer text responses

337

superagent.buffer['image/jpeg'] = false; // Don't buffer images

338

339

// Request-level buffering override

340

superagent

341

.get('https://api.example.com/large-json')

342

.buffer(false) // Don't buffer this large response

343

.parse((res, callback) => {

344

// Handle streaming response

345

let data = '';

346

res.on('data', chunk => data += chunk);

347

res.on('end', () => {

348

try {

349

const parsed = JSON.parse(data);

350

callback(null, parsed);

351

} catch (err) {

352

callback(err);

353

}

354

});

355

});

356

```

357

358

### Advanced Parser Patterns

359

360

Complex parsing scenarios and patterns.

361

362

```javascript

363

// Multi-format parser based on content

364

superagent

365

.get('https://api.example.com/dynamic-format')

366

.parse((res, callback) => {

367

const contentType = res.headers['content-type'] || '';

368

369

if (contentType.includes('application/json')) {

370

try {

371

callback(null, JSON.parse(res.text));

372

} catch (err) {

373

callback(err);

374

}

375

} else if (contentType.includes('application/xml')) {

376

// Parse XML

377

callback(null, parseXML(res.text));

378

} else if (contentType.includes('text/csv')) {

379

// Parse CSV

380

callback(null, parseCSV(res.text));

381

} else {

382

// Default to text

383

callback(null, res.text);

384

}

385

});

386

387

// Streaming parser for large responses

388

superagent

389

.get('https://api.example.com/large-dataset')

390

.buffer(false)

391

.parse((res, callback) => {

392

const results = [];

393

let buffer = '';

394

395

res.on('data', (chunk) => {

396

buffer += chunk;

397

398

// Process complete JSON objects (newline-delimited JSON)

399

const lines = buffer.split('\n');

400

buffer = lines.pop(); // Keep incomplete line

401

402

lines.forEach(line => {

403

if (line.trim()) {

404

try {

405

results.push(JSON.parse(line));

406

} catch (err) {

407

// Skip invalid lines

408

}

409

}

410

});

411

});

412

413

res.on('end', () => {

414

// Process remaining buffer

415

if (buffer.trim()) {

416

try {

417

results.push(JSON.parse(buffer));

418

} catch (err) {

419

// Ignore final parse error

420

}

421

}

422

callback(null, results);

423

});

424

425

res.on('error', callback);

426

});

427

428

// Conditional parser with fallback

429

superagent

430

.get('https://api.example.com/data')

431

.parse((res, callback) => {

432

// Try JSON first

433

try {

434

const jsonData = JSON.parse(res.text);

435

callback(null, { format: 'json', data: jsonData });

436

return;

437

} catch (jsonErr) {

438

// Fall back to form data

439

try {

440

const formData = parseFormData(res.text);

441

callback(null, { format: 'form', data: formData });

442

return;

443

} catch (formErr) {

444

// Fall back to plain text

445

callback(null, { format: 'text', data: res.text });

446

}

447

}

448

});

449

```

450

451

### Error Handling in Parsers

452

453

Handle parsing errors gracefully.

454

455

```javascript

456

// Robust JSON parser with error recovery

457

superagent

458

.get('https://api.example.com/potentially-invalid-json')

459

.parse((res, callback) => {

460

try {

461

const data = JSON.parse(res.text);

462

callback(null, data);

463

} catch (err) {

464

// Attempt to fix common JSON issues

465

let fixedText = res.text

466

.replace(/,\s*}/g, '}') // Remove trailing commas

467

.replace(/,\s*]/g, ']') // Remove trailing commas in arrays

468

.replace(/'/g, '"'); // Replace single quotes with double quotes

469

470

try {

471

const fixedData = JSON.parse(fixedText);

472

console.warn('JSON was malformed but successfully repaired');

473

callback(null, fixedData);

474

} catch (secondErr) {

475

// If repair fails, return original error with more context

476

const error = new Error(`JSON parsing failed: ${err.message}`);

477

error.originalText = res.text;

478

error.responseStatus = res.status;

479

callback(error);

480

}

481

}

482

});

483

484

// Parser with validation

485

superagent

486

.get('https://api.example.com/api-data')

487

.parse((res, callback) => {

488

try {

489

const data = JSON.parse(res.text);

490

491

// Validate expected structure

492

if (!data.hasOwnProperty('success')) {

493

return callback(new Error('Missing required field: success'));

494

}

495

496

if (!Array.isArray(data.items)) {

497

return callback(new Error('Expected items to be an array'));

498

}

499

500

callback(null, data);

501

} catch (err) {

502

callback(err);

503

}

504

});

505

```