Progressive JSON streaming parser that enables processing data as it arrives over HTTP without waiting for the complete response
94
The OboeInstance provides an event-driven API for listening to JSON parsing events, including pattern-based node matching, lifecycle events, and error handling. All methods return the instance for method chaining.
Add and remove event listeners using EventEmitter-style methods.
/**
* Add event listener
* @param {string} event - Event name
* @param {Function} callback - Event handler function
* @returns {OboeInstance} The instance for chaining
*/
on(event: string, callback: Function): OboeInstance;
/**
* Add event listener (alias for on)
* @param {string} event - Event name
* @param {Function} callback - Event handler function
* @returns {OboeInstance} The instance for chaining
*/
addListener(event: string, callback: Function): OboeInstance;
/**
* Remove event listener
* @param {string} event - Event name
* @param {Function} callback - Event handler function to remove
* @returns {OboeInstance} The instance for chaining
*/
removeListener(event: string, callback?: Function): OboeInstance;
/**
* Manually emit events
* @param {string} event - Event to emit
* @param {...any} args - Arguments to pass to listeners
*/
emit(event: string, ...args: any[]): void;Standard Events:
'start' - HTTP request has started'done' - JSON parsing completed successfully'fail' - Error occurred during request or parsing'node:pattern' - Node matching pattern found'path:pattern' - Path matching pattern foundUsage Examples:
const request = oboe('https://api.example.com/data.json');
// Standard event listeners
request
.on('start', function(statusCode, headers) {
console.log('Request started:', statusCode);
})
.on('done', function(json) {
console.log('Parsing complete:', json);
})
.on('fail', function(error) {
console.error('Failed:', error);
});
// Fully-qualified pattern events
request.on('node:!.users.*', function(user, path, ancestors) {
console.log('User found:', user);
});
// Remove specific listener
const userHandler = function(user) { console.log(user); };
request.on('node:!.users.*', userHandler);
request.removeListener('node:!.users.*', userHandler);Listen for JSON nodes that match specific JSONPath patterns.
/**
* Listen for nodes matching JSONPath pattern
* @param {string|object} pattern - JSONPath pattern or pattern map
* @param {NodeCallback} callback - Called when pattern matches (optional if using pattern map)
* @returns {OboeInstance} The instance for chaining
*/
node(pattern: string | PatternMap, callback?: NodeCallback): OboeInstance;
type NodeCallback = (node: any, path: string[], ancestors: any[]) => void;
interface PatternMap {
[pattern: string]: NodeCallback;
}Usage Examples:
// Single pattern with callback
oboe('https://api.example.com/users.json')
.node('!.users.*', function(user, path, ancestors) {
console.log('User:', user);
console.log('Path:', path); // ['users', '0'], ['users', '1'], etc.
console.log('Ancestors:', ancestors); // [rootObject, usersArray]
});
// Multiple patterns using pattern map
oboe('https://api.example.com/data.json')
.node({
'!.users.*': function(user) {
console.log('User found:', user.name);
},
'!.posts.*': function(post) {
console.log('Post found:', post.title);
},
'!.comments.*': function(comment) {
console.log('Comment found:', comment.text);
}
});
// Pattern with field selection
oboe('https://api.example.com/users.json')
.node('!.users.*{name email}', function(user) {
// Only name and email fields are included
console.log(user); // { name: "John", email: "john@example.com" }
});Listen for JSON paths that match specific JSONPath patterns.
/**
* Listen for paths matching JSONPath pattern
* @param {string|object} pattern - JSONPath pattern or pattern map
* @param {PathCallback} callback - Called when pattern matches (optional if using pattern map)
* @returns {OboeInstance} The instance for chaining
*/
path(pattern: string | PatternMap, callback?: PathCallback): OboeInstance;
type PathCallback = (path: string[], ancestors: any[]) => void;Usage Examples:
// Listen for array paths
oboe('https://api.example.com/data.json')
.path('!.items', function(path, ancestors) {
console.log('Found items array at path:', path); // ['items']
console.log('Root object:', ancestors[0]);
});
// Multiple path patterns
oboe('https://api.example.com/nested.json')
.path({
'!.data': function(path) {
console.log('Data section found');
},
'!.data.users': function(path) {
console.log('Users array found');
},
'!.data.users.*': function(path) {
console.log('User path:', path); // ['data', 'users', '0'], etc.
}
});Listen for HTTP request initiation.
/**
* Listen for HTTP request start
* @param {StartCallback} callback - Called when request starts
* @returns {OboeInstance} The instance for chaining
*/
start(callback: StartCallback): OboeInstance;
type StartCallback = (statusCode: number, headers: Record<string, string>) => void;Usage Example:
oboe('https://api.example.com/data.json')
.start(function(statusCode, headers) {
console.log('Request started with status:', statusCode);
console.log('Content-Type:', headers['content-type']);
console.log('Content-Length:', headers['content-length']);
});Listen for successful completion of JSON parsing.
/**
* Listen for parsing completion
* @param {DoneCallback} callback - Called when parsing completes successfully
* @returns {OboeInstance} The instance for chaining
*/
done(callback: DoneCallback): OboeInstance;
type DoneCallback = (json: any) => void;Usage Example:
oboe('https://api.example.com/data.json')
.done(function(completeJson) {
console.log('Parsing complete. Full JSON:', completeJson);
console.log('Total items:', completeJson.items.length);
});Listen for errors during request or parsing.
/**
* Listen for errors
* @param {FailCallback} callback - Called when errors occur
* @returns {OboeInstance} The instance for chaining
*/
fail(callback: FailCallback): OboeInstance;
type FailCallback = (error: OboeError) => void;
interface OboeError {
/** Original thrown error (if applicable) */
thrown?: Error;
/** HTTP status code (if HTTP error) */
statusCode?: number;
/** Response body (if available) */
body?: string;
/** Parsed JSON response body (if applicable) */
jsonBody?: any;
}Usage Example:
oboe('https://api.example.com/data.json')
.fail(function(error) {
if (error.statusCode) {
console.error('HTTP Error:', error.statusCode);
console.error('Response:', error.body);
} else if (error.thrown) {
console.error('Parsing Error:', error.thrown.message);
} else {
console.error('Unknown Error:', error);
}
});Cancel the HTTP request and stop JSON parsing.
/**
* Abort the HTTP request and JSON parsing
*/
abort(): void;Usage Example:
const request = oboe('https://api.example.com/large-data.json');
// Abort after 5 seconds
setTimeout(function() {
request.abort();
console.log('Request aborted');
}, 5000);Available within callbacks to unregister the current callback. Only callable from within node/path callbacks.
/**
* Unregister the current callback (only available within callbacks)
*/
forget(): void;Usage Example:
oboe('https://api.example.com/stream.json')
.node('!.items.*', function(item) {
console.log('Processing item:', item.id);
if (item.id === 'stop-processing') {
this.forget(); // Stop receiving more items
console.log('Stopped processing items');
}
});Access HTTP response headers once the request has started.
/**
* Access HTTP response headers
* @param {string} name - Optional specific header name
* @returns {any} Header value (if name provided) or headers object (if no name)
*/
header(name?: string): any;Usage Examples:
const request = oboe('https://api.example.com/data.json');
request.start(function() {
// Get all headers
const headers = request.header();
console.log('All headers:', headers);
// Get specific header
const contentType = request.header('content-type');
console.log('Content-Type:', contentType);
// Case-insensitive header access
const length = request.header('Content-Length');
console.log('Content Length:', length);
});Access the root JSON object once parsing is complete.
/**
* Access the root JSON object
* @returns {any} The complete parsed JSON object (undefined until parsing completes)
*/
root(): any;Usage Example:
const request = oboe('https://api.example.com/data.json');
request.done(function() {
const rootObject = request.root();
console.log('Root object:', rootObject);
console.log('Total users:', rootObject.users.length);
});Access the URL or source identifier for this oboe instance.
/**
* The URL or source identifier for this instance
*/
source: string;Usage Example:
const request = oboe('https://api.example.com/data.json');
console.log('Requesting:', request.source);
// Output: "Requesting: https://api.example.com/data.json"
// Available in callbacks too
request.done(function() {
console.log('Completed request to:', this.source);
});All methods except abort(), emit(), header(), root(), and source return the instance for fluent chaining:
oboe('https://api.example.com/data.json')
.start(logStart)
.node('!.users.*', processUser)
.node('!.posts.*', processPost)
.path('!.metadata', processMetadata)
.done(handleComplete)
.fail(handleError);Within all callbacks, this refers to the oboe instance, providing access to all instance methods and properties:
oboe('https://api.example.com/data.json')
.node('!.users.*', function(user) {
console.log('Processing user from:', this.source);
if (user.premium) {
// Access other methods via 'this'
this.node('!.premium-features.*', handlePremiumFeature);
}
});Install with Tessl CLI
npx tessl i tessl/npm-oboeevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10