outputparsers
- parseJSON - Parses JSON string and returns a result object with success flag and parsed data or error.
- parseXML - Parses XML string and returns a result object with success flag and parsed data.
- parseCSV - Parses CSV string and returns a result object with success flag and parsed array of objects.
- parseText - Parses text string and returns a result object with success flag and parsed lines array.
Overview
The Output Parsers module provides robust parsing capabilities for various data formats including JSON, XML, CSV, and plain text. Each parser returns a consistent result object with success flags and appropriate error handling.
Quick Start
import codebolt from '@codebolt/codeboltjs';
// Parse JSON
const jsonResult = await codebolt.outputparsers.parseJSON('{"name": "test", "value": 123}');
if (jsonResult.success) {
console.log(jsonResult.parsed);
}
// Parse CSV
const csvResult = await codebolt.outputparsers.parseCSV('name,age\nJohn,25\nJane,30');
if (csvResult.success) {
console.log(csvResult.parsed);
}
// Parse Text
const textResult = await codebolt.outputparsers.parseText('Line 1\nLine 2\nLine 3');
if (textResult.success) {
console.log(textResult.parsed);
}
// Parse XML
const xmlResult = await codebolt.outputparsers.parseXML('<root><item>Test</item></root>');
if (xmlResult.success) {
console.log(xmlResult.parsed);
}
Common Workflows
1. Multi-Format Data Processing
class DataProcessor {
async processData(data, format) {
const parsers = {
json: codebolt.outputparsers.parseJSON.bind(codebolt.outputparsers),
xml: codebolt.outputparsers.parseXML.bind(codebolt.outputparsers),
csv: codebolt.outputparsers.parseCSV.bind(codebolt.outputparsers),
text: codebolt.outputparsers.parseText.bind(codebolt.outputparsers)
};
const parser = parsers[format.toLowerCase()];
if (!parser) {
return {
success: false,
error: `Unsupported format: ${format}`
};
}
return await parser(data);
}
async detectAndParse(data) {
// Try to detect format automatically
if (data.trim().startsWith('{') || data.trim().startsWith('[')) {
return await this.processData(data, 'json');
} else if (data.trim().startsWith('<')) {
return await this.processData(data, 'xml');
} else if (data.includes(',')) {
return await this.processData(data, 'csv');
} else {
return await this.processData(data, 'text');
}
}
}
// Usage
const processor = new DataProcessor();
const result = await processor.detectAndParse('{"key": "value"}');
2. Batch File Processing
async function batchParseFiles(files) {
const results = [];
for (const file of files) {
const extension = file.name.split('.').pop().toLowerCase();
let parser;
switch (extension) {
case 'json':
parser = codebolt.outputparsers.parseJSON;
break;
case 'xml':
parser = codebolt.outputparsers.parseXML;
break;
case 'csv':
parser = codebolt.outputparsers.parseCSV;
break;
default:
parser = codebolt.outputparsers.parseText;
}
try {
const result = await parser(file.content);
results.push({
file: file.name,
format: extension,
success: result.success,
data: result.parsed || result.error
});
} catch (error) {
results.push({
file: file.name,
format: extension,
success: false,
error: error.message
});
}
}
return results;
}
3. Data Validation Pipeline
class DataValidationPipeline {
async validateAndParse(data, format, schema) {
// Parse the data
const parseResult = await codebolt.outputparsers[`parse${format.toUpperCase()}`](data);
if (!parseResult.success) {
return {
valid: false,
error: `Parsing failed: ${parseResult.error}`
};
}
const parsed = parseResult.parsed;
// Validate against schema
const validationResult = this.validateSchema(parsed, schema);
return {
valid: validationResult.valid,
data: parsed,
errors: validationResult.errors
};
}
validateSchema(data, schema) {
const errors = [];
for (const [key, type] of Object.entries(schema)) {
if (!(key in data)) {
errors.push(`Missing required field: ${key}`);
continue;
}
if (typeof data[key] !== type) {
errors.push(`Invalid type for ${key}: expected ${type}, got ${typeof data[key]}`);
}
}
return {
valid: errors.length === 0,
errors
};
}
}
// Usage
const pipeline = new DataValidationPipeline();
const result = await pipeline.validateAndParse(
'{"name": "John", "age": 25}',
'json',
{ name: 'string', age: 'number' }
);
4. Format Conversion
class FormatConverter {
async convert(data, fromFormat, toFormat) {
// Parse source format
const parseResult = await codebolt.outputparsers[`parse${fromFormat.toUpperCase()}`](data);
if (!parseResult.success) {
return {
success: false,
error: `Failed to parse ${fromFormat}: ${parseResult.error}`
};
}
const parsed = parseResult.parsed;
// Convert to target format
let converted;
switch (toFormat.toLowerCase()) {
case 'json':
converted = JSON.stringify(parsed, null, 2);
break;
case 'csv':
converted = this.toCSV(parsed);
break;
case 'xml':
converted = this.toXML(parsed);
break;
default:
return {
success: false,
error: `Unsupported target format: ${toFormat}`
};
}
return {
success: true,
data: converted
};
}
toCSV(data) {
if (Array.isArray(data) && data.length > 0) {
const headers = Object.keys(data[0]);
const rows = data.map(obj => headers.map(h => obj[h]).join(','));
return [headers.join(','), ...rows].join('\n');
}
return '';
}
toXML(data) {
return `<root>${JSON.stringify(data)}</root>`;
}
}
// Usage
const converter = new FormatConverter();
const result = await converter.convert(
'[{"name": "John", "age": 25}]',
'json',
'csv'
);
Best Practices
Error Handling
async function safeParse(parser, data) {
try {
const result = await parser(data);
if (!result.success) {
console.error('Parse failed:', result.error);
return {
success: false,
error: result.error,
fallback: null
};
}
return {
success: true,
data: result.parsed
};
} catch (error) {
console.error('Parse error:', error);
return {
success: false,
error: error.message,
fallback: null
};
}
}
Data Sanitization
async function parseWithSanitization(parser, data) {
// Sanitize input
const sanitized = data
.trim()
.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]/g, ''); // Remove control characters
const result = await parser(sanitized);
if (result.success) {
// Sanitize output
result.parsed = sanitizeOutput(result.parsed);
}
return result;
}
function sanitizeOutput(data) {
if (typeof data === 'string') {
return data.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}
if (Array.isArray(data)) {
return data.map(sanitizeOutput);
}
if (typeof data === 'object' && data !== null) {
const sanitized = {};
for (const [key, value] of Object.entries(data)) {
sanitized[key] = sanitizeOutput(value);
}
return sanitized;
}
return data;
}
Integration Examples
With File System
async function parseFileFromFS(filePath) {
const content = await codebolt.fs.readFile(filePath);
const extension = filePath.split('.').pop().toLowerCase();
const parsers = {
json: codebolt.outputparsers.parseJSON,
xml: codebolt.outputparsers.parseXML,
csv: codebolt.outputparsers.parseCSV,
txt: codebolt.outputparsers.parseText
};
const parser = parsers[extension] || codebolt.outputparsers.parseText;
return await parser(content);
}
With Chat Module
async function parseChatResponse(response, expectedFormat) {
const parser = codebolt.outputparsers[`parse${expectedFormat.toUpperCase()}`];
try {
const result = await parser(response);
if (!result.success) {
// Ask chat to fix the format
const clarification = await codebolt.chat.sendMessage(
`The previous response was not valid ${expectedFormat}. Please provide the data in correct ${expectedFormat} format.`
);
return await parser(clarification);
}
return result;
} catch (error) {
console.error('Failed to parse chat response:', error);
throw error;
}
}
Common Pitfalls
Pitfall 1: Not Checking Success Flag
// ❌ Wrong
const result = await codebolt.outputparsers.parseJSON(data);
console.log(result.parsed.name); // May throw error
// ✅ Correct
const result = await codebolt.outputparsers.parseJSON(data);
if (result.success) {
console.log(result.parsed.name);
} else {
console.error('Parse failed:', result.error);
}
Pitfall 2: Assuming Format
// ❌ Wrong - assumes valid JSON
const parsed = JSON.parse(userInput);
// ✅ Correct - validate and parse
const result = await codebolt.outputparsers.parseJSON(userInput);
if (!result.success) {
console.error('Invalid JSON:', result.error);
return;
}
Performance Considerations
- Large Files: For large files (>10MB), consider streaming or chunking
- Batch Operations: Process multiple files in parallel for better performance
- Caching: Cache parsed results if data is accessed frequently
- Validation: Validate structure before parsing to fail fast
Advanced Patterns
Streaming Parser
class StreamingDataProcessor {
constructor(chunkSize = 1024) {
this.chunkSize = chunkSize;
}
async processStream(stream, parser) {
const chunks = [];
let buffer = '';
for await (const chunk of stream) {
buffer += chunk;
while (buffer.length >= this.chunkSize) {
const chunk = buffer.slice(0, this.chunkSize);
buffer = buffer.slice(this.chunkSize);
const result = await parser(chunk);
chunks.push(result);
}
}
// Process remaining buffer
if (buffer) {
const result = await parser(buffer);
chunks.push(result);
}
return chunks;
}
}