CARVIEW |
Select Language
HTTP/2 200
date: Wed, 23 Jul 2025 06:52:30 GMT
content-type: text/html; charset=utf-8
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
etag: W/"e4f83696773324f5811541b82358184c"
cache-control: max-age=0, private, must-revalidate
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
content-encoding: gzip
accept-ranges: bytes
set-cookie: _gh_sess=Wl%2BTogCjSxR5TylugieKGm8%2FOUnnASFpaveo5vbIFy4tzDQpgORSoiIWeGwgmBbqpYyvniEXaywM%2BXGbYyR5%2FB28Wfu2RgIUmnSXiiqNZxVn5Fuh6qayFmjP5yP%2Bh8kubyFLMGCzgxgUp2l6gRE18LxAaZeQV8a%2B76uVnUNUoguMzFW9fXd3VgDugxjFbx9C%2BxR9Ac1bkYO2N5vDKWmG%2BZ%2FXRjVgXEXV9Eb%2BN0kzVE3XfJWWRScJRzhlZFMbNjKrP2LpoRs8cVEEjw1HtIDKlQ%3D%3D--WFoW0XJWbYrM%2BqcK--2MciuoB6FSgaprynCKi3RA%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax
set-cookie: _octo=GH1.1.1153995193.1753253549; Path=/; Domain=github.com; Expires=Thu, 23 Jul 2026 06:52:29 GMT; Secure; SameSite=Lax
set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Thu, 23 Jul 2026 06:52:29 GMT; HttpOnly; Secure; SameSite=Lax
x-github-request-id: C20C:3B93B0:5965B7:71F4D0:688086AD
event-only version of jsonparse · GitHub
Show Gist options
Save creationix/1821394 to your computer and use it in GitHub Desktop.
{{ message }}
Instantly share code, notes, and snippets.
Created
February 13, 2012 23:20
-
Star
41
(41)
You must be signed in to star a gist -
Fork
10
(10)
You must be signed in to fork a gist
-
Save creationix/1821394 to your computer and use it in GitHub Desktop.
event-only version of jsonparse
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Named constants with unique integer values | |
var C = {}; | |
// Tokenizer States | |
var START = C.START = 0x11; | |
var TRUE1 = C.TRUE1 = 0x21; | |
var TRUE2 = C.TRUE2 = 0x22; | |
var TRUE3 = C.TRUE3 = 0x23; | |
var FALSE1 = C.FALSE1 = 0x31; | |
var FALSE2 = C.FALSE2 = 0x32; | |
var FALSE3 = C.FALSE3 = 0x33; | |
var FALSE4 = C.FALSE4 = 0x34; | |
var NULL1 = C.NULL1 = 0x41; | |
var NULL2 = C.NULL3 = 0x42; | |
var NULL3 = C.NULL2 = 0x43; | |
var NUMBER1 = C.NUMBER1 = 0x51; | |
var NUMBER2 = C.NUMBER2 = 0x52; | |
var NUMBER3 = C.NUMBER3 = 0x53; | |
var NUMBER4 = C.NUMBER4 = 0x54; | |
var NUMBER5 = C.NUMBER5 = 0x55; | |
var NUMBER6 = C.NUMBER6 = 0x56; | |
var NUMBER7 = C.NUMBER7 = 0x57; | |
var NUMBER8 = C.NUMBER8 = 0x58; | |
var STRING1 = C.STRING1 = 0x61; | |
var STRING2 = C.STRING2 = 0x62; | |
var STRING3 = C.STRING3 = 0x63; | |
var STRING4 = C.STRING4 = 0x64; | |
var STRING5 = C.STRING5 = 0x65; | |
var STRING6 = C.STRING6 = 0x66; | |
// Slow code to string converter (only used when throwing syntax errors) | |
function toknam(code) { | |
var keys = Object.keys(C); | |
for (var i = 0, l = keys.length; i < l; i++) { | |
var key = keys[i]; | |
if (C[key] === code) { return key; } | |
} | |
return code && ("0x" + code.toString(16)); | |
} | |
function SaxParser(callbacks) { | |
this.callbacks = callbacks; | |
this.state = START; | |
// for string parsing | |
this.string = undefined; // string data | |
this.unicode = undefined; // unicode escapes | |
// For number parsing | |
this.negative = undefined; | |
this.magnatude = undefined; | |
this.position = undefined; | |
this.exponent = undefined; | |
this.negativeExponent = undefined; | |
} | |
var proto = SaxParser.prototype; | |
proto.charError = function (buffer, i) { | |
this.callbacks.onError(new Error("Unexpected " + JSON.stringify(String.fromCharCode(buffer[i])) + " at position " + i + " in state " + toknam(this.state))); | |
}; | |
proto.parse = function (buffer) { | |
if (typeof buffer === "string") buffer = new Buffer(buffer); | |
var n; | |
for (var i = 0, l = buffer.length; i < l; i++) { | |
switch (this.state) { | |
case START: | |
n = buffer[i]; | |
switch (n) { | |
case 0x7b: // `{` | |
this.callbacks.onStartObject(); | |
continue; | |
case 0x7d: // `}` | |
this.callbacks.onEndObject(); | |
continue; | |
case 0x5b: // `[` | |
this.callbacks.onStartArray(); | |
continue; | |
case 0x5d: // `]` | |
this.callbacks.onEndArray(); | |
continue; | |
case 0x3a: // `:` | |
this.callbacks.onColon(); | |
continue; | |
case 0x2c: // `,` | |
this.callbacks.onComma(); | |
continue; | |
case 0x74: // `t` | |
this.state = TRUE1; | |
continue; | |
case 0x66: // `f` | |
this.state = FALSE1; | |
continue; | |
case 0x6e: // `n` | |
this.state = NULL1; | |
continue; | |
case 0x22: // `"` | |
this.string = ""; | |
this.state = STRING1; | |
continue; | |
case 0x2d: // `-` | |
this.negative = true; | |
this.state = NUMBER1; | |
continue; | |
case 0x30: // `0` | |
this.magnatude = 0; | |
this.state = NUMBER2; | |
continue; | |
} | |
if (n > 0x30 && n < 0x40) { // 1-9 | |
this.magnatude = n - 0x30; | |
this.state = NUMBER3; | |
continue; | |
} | |
if (n === 0x20 || n === 0x09 || n === 0x0a || n === 0x0d) { | |
continue; // whitespace | |
} | |
this.charError(buffer, i); | |
case STRING1: // After open quote | |
n = buffer[i]; | |
switch (n) { | |
case 0x22: // `"` | |
this.callbacks.onString(this.string); | |
this.string = undefined; | |
this.state = START; | |
continue; | |
case 0x5c: // `\` | |
this.state = STRING2; | |
continue; | |
} | |
if (n >= 0x20) { | |
this.string += String.fromCharCode(n); | |
continue; | |
} | |
this.charError(buffer, i); | |
case STRING2: // After backslash | |
n = buffer[i]; | |
switch (n) { | |
case 0x22: this.string += "\""; this.state = STRING1; continue; | |
case 0x5c: this.string += "\\"; this.state = STRING1; continue; | |
case 0x2f: this.string += "\/"; this.state = STRING1; continue; | |
case 0x62: this.string += "\b"; this.state = STRING1; continue; | |
case 0x66: this.string += "\f"; this.state = STRING1; continue; | |
case 0x6e: this.string += "\n"; this.state = STRING1; continue; | |
case 0x72: this.string += "\r"; this.state = STRING1; continue; | |
case 0x74: this.string += "\t"; this.state = STRING1; continue; | |
case 0x75: this.unicode = ""; this.state = STRING3; continue; | |
} | |
this.charError(buffer, i); | |
case STRING3: case STRING4: case STRING5: case STRING6: // unicode hex codes | |
n = buffer[i]; | |
// 0-9 A-F a-f | |
if ((n >= 0x30 && n < 0x40) || (n > 0x40 && n <= 0x46) || (n > 0x60 && n <= 0x66)) { | |
this.unicode += String.fromCharCode(n); | |
if (this.state++ === STRING6) { | |
this.string += String.fromCharCode(parseInt(this.unicode, 16)); | |
this.unicode = undefined; | |
this.state = STRING1; | |
} | |
continue; | |
} | |
this.charError(buffer, i); | |
case NUMBER1: // after minus | |
n = buffer[i]; | |
if (n === 0x30) { // `0` | |
this.magnatude = 0; | |
this.state = NUMBER2; | |
continue; | |
} | |
if (n > 0x30 && n < 0x40) { // `1`-`9` | |
this.magnatude = n - 0x30; | |
this.state = NUMBER3; | |
continue; | |
} | |
this.charError(buffer, i); | |
case NUMBER2: // * After initial zero | |
switch (buffer[i]) { | |
case 0x2e: // . | |
this.position = 0.1; this.state = NUMBER4; continue; | |
case 0x65: case 0x45: // e/E | |
this.exponent = 0; this.state = NUMBER6; continue; | |
} | |
this.finish(); | |
i--; // rewind to re-check this char | |
continue; | |
case NUMBER3: // * After digit (before period) | |
n = buffer[i]; | |
switch (n) { | |
case 0x2e: // . | |
this.position = 0.1; this.state = NUMBER4; continue; | |
case 0x65: case 0x45: // e/E | |
this.exponent = 0; this.state = NUMBER6; continue; | |
} | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.magnatude = this.magnatude * 10 + (n - 0x30); | |
continue; | |
} | |
this.finish(); | |
i--; // rewind to re-check | |
continue; | |
case NUMBER4: // After period | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.magnatude += this.position * (n - 0x30); | |
this.position /= 10; | |
this.state = NUMBER5; | |
continue; | |
} | |
this.charError(buffer, i); | |
case NUMBER5: // * After digit (after period) | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.magnatude += this.position * (n - 0x30); | |
this.position /= 10; | |
continue; | |
} | |
if (n === 0x65 || n === 0x45) { // E/e | |
this.exponent = 0; | |
this.state = NUMBER6; | |
continue; | |
} | |
this.finish(); | |
i--; // rewind | |
continue; | |
case NUMBER6: // After E | |
n = buffer[i]; | |
if (n === 0x2b || n === 0x2d) { // +/- | |
if (n === 0x2d) { this.negativeExponent = true; } | |
this.state = NUMBER7; | |
continue; | |
} | |
if (n >= 0x30 && n < 0x40) { | |
this.exponent = this.exponent * 10 + (n - 0x30); | |
this.state = NUMBER8; | |
continue; | |
} | |
this.charError(buffer, i); | |
case NUMBER7: // After +/- | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.exponent = this.exponent * 10 + (n - 0x30); | |
this.state = NUMBER8; | |
continue; | |
} | |
this.charError(buffer, i); | |
case NUMBER8: // * After digit (after +/-) | |
n = buffer[i]; | |
if (n >= 0x30 && n < 0x40) { // 0-9 | |
this.exponent = this.exponent * 10 + (n - 0x30); | |
continue; | |
} | |
this.finish(); | |
i--; | |
continue; | |
case TRUE1: // r | |
if (buffer[i] === 0x72) { | |
this.state = TRUE2; | |
continue; | |
} | |
this.charError(buffer, i); | |
case TRUE2: // u | |
if (buffer[i] === 0x75) { | |
this.state = TRUE3; | |
continue; | |
} | |
this.charError(buffer, i); | |
case TRUE3: // e | |
if (buffer[i] === 0x65) { | |
this.state = START; | |
this.callbacks.onBoolean(true); | |
continue; | |
} | |
this.charError(buffer, i); | |
case FALSE1: // a | |
if (buffer[i] === 0x61) { | |
this.state = FALSE2; | |
continue; | |
} | |
this.charError(buffer, i); | |
case FALSE2: // l | |
if (buffer[i] === 0x6c) { | |
this.state = FALSE3; | |
continue; | |
} | |
this.charError(buffer, i); | |
case FALSE3: // s | |
if (buffer[i] === 0x73) { | |
this.state = FALSE4; | |
continue; | |
} | |
this.charError(buffer, i); | |
case FALSE4: // e | |
if (buffer[i] === 0x65) { | |
this.state = START; | |
this.callbacks.onBoolean(false); | |
continue; | |
} | |
this.charError(buffer, i); | |
case NULL1: // u | |
if (buffer[i] === 0x75) { | |
this.state = NULL2; | |
continue; | |
} | |
this.charError(buffer, i); | |
case NULL2: // l | |
if (buffer[i] === 0x6c) { | |
this.state = NULL3; | |
continue; | |
} | |
this.charError(buffer, i); | |
case NULL3: // l | |
if (buffer[i] === 0x6c) { | |
this.state = START; | |
this.callbacks.onNull(); | |
continue; | |
} | |
this.charError(buffer, i); | |
} | |
} | |
}; | |
proto.finish = function () { | |
switch (this.state) { | |
case NUMBER2: // * After initial zero | |
this.callbacks.onNumber(0); | |
this.state = START; | |
this.magnatude = undefined; | |
this.negative = undefined; | |
break; | |
case NUMBER3: // * After digit (before period) | |
this.state = START; | |
if (this.negative) { | |
this.magnatude = -this.magnatude; | |
this.negative = undefined; | |
} | |
this.callbacks.onNumber(this.magnatude); | |
this.magnatude = undefined; | |
break; | |
case NUMBER5: // * After digit (after period) | |
this.state = START; | |
if (this.negative) { | |
this.magnatude = -this.magnatude; | |
this.negative = undefined; | |
} | |
this.callbacks.onNumber(this.negative ? -this.magnatude : this.magnatude); | |
this.magnatude = undefined; | |
this.position = undefined; | |
break; | |
case NUMBER8: // * After digit (after +/-) | |
if (this.negativeExponent) { | |
this.exponent = -this.exponent; | |
this.negativeExponent = undefined; | |
} | |
this.magnatude *= Math.pow(10, this.exponent); | |
this.exponent = undefined; | |
if (this.negative) { | |
this.magnatude = -this.magnatude; | |
this.negative = undefined; | |
} | |
this.state = START; | |
this.callbacks.onNumber(this.magnatude); | |
this.magnatude = undefined; | |
break; | |
} | |
if (this.state !== START) { | |
this.callbacks.onError(new Error("Unexpected end of input stream")); | |
} | |
} | |
exports.SaxParser = SaxParser; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var SaxParser = require('./jsonparse').SaxParser; | |
var p = new SaxParser({ | |
onNull: function () { | |
console.log("onNull"); | |
}, | |
onBoolean: function (value) { | |
console.log("onBoolean", value); | |
}, | |
onNumber: function (value) { | |
console.log("onNumber", value); | |
}, | |
onString: function (value) { | |
console.log("onString", value); | |
}, | |
onStartObject: function () { | |
console.log("onStartObject"); | |
}, | |
onColon: function () { | |
console.log("onColon"); | |
}, | |
onComma: function () { | |
console.log("onComma"); | |
}, | |
onEndObject: function () { | |
console.log("onEndObject"); | |
}, | |
onStartArray: function () { | |
console.log("onStartArray"); | |
}, | |
onEndArray: function () { | |
console.log("onEndArray"); | |
} | |
}); | |
//var stream = require('fs').createReadStream(__dirname + "/tests/sample.json"); | |
//var parse = p.parse.bind(p); | |
//stream.on('data', parse); | |
//p.parse(new Buffer("{}")); | |
//p.parse(new Buffer("[]")); | |
//p.parse(new Buffer('"Hello"')); | |
p.parse(new Buffer("[1,2,3]")); | |
p.parse(new Buffer("-0.1e-3")); | |
p.parse(new Buffer('"Hello"')); | |
p.finish() | |
//p.parse(new Buffer('{"name":"tim"}')) |
this is cool, but how do I use it? Right now I am using JSONStream...but I am wondering if there is a way to use this module directly. Dunno, cuz there are no examples that I see. Nice code though :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can’t perform that action at this time.
Is the null numbering on purpose?
NULL2
equalsC.NULL3
NULL3
equalsC.NULL2