Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- json_parse_raw.js
- 2012-03-26
- based on json_parse.js
- 2011-03-06
- Public Domain.
- NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
- This file creates a json_parse_raw function.
- json_parse_raw(text, reviver)
- This method parses the first JSON text in a string to
- produce an object or array and the position of the first
- character past the JSON text. If given an empty string or
- an incomplete JSON text, it will return [undefined, 0]. If
- given invalid JSON, it will throw a SyntaxError exception.
- The optional reviver parameter is a function that can filter and
- transform the results. It receives each of the keys and values,
- and its return value is used instead of the original value.
- If it returns what it received, then the structure is not modified.
- If it returns undefined then the member is deleted.
- Example:
- // Parse the text. Values that look like ISO date strings will
- // be converted to Date objects.
- myData = json_parse_raw(text, function (key, value) {
- var a;
- if (typeof value === 'string') {
- a =
- /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
- if (a) {
- return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
- +a[5], +a[6]));
- }
- }
- return value;
- });
- This is a reference implementation. You are free to copy, modify, or
- redistribute.
- This code should be minified before deployment.
- See http://javascript.crockford.com/jsmin.html
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
- NOT CONTROL.
- */
- /*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode,
- hasOwnProperty, message, n, name, prototype, push, r, t, text
- */
- var json_parse_raw = (function () {
- "use strict";
- // This is a function that can parse a JSON text, producing a JavaScript
- // data structure. It is a simple, recursive descent parser. It does not use
- // eval or regular expressions, so it can be used as a model for implementing
- // a JSON parser in other languages.
- // We are defining the function inside of another function to avoid creating
- // global variables.
- var at, // The index of the current character
- ch, // The current character
- escapee = {
- '"': '"',
- '\\': '\\',
- '/': '/',
- b: '\b',
- f: '\f',
- n: '\n',
- r: '\r',
- t: '\t'
- },
- text,
- error = function (m) {
- // Call error when something is wrong.
- throw {
- name: 'SyntaxError',
- message: m,
- at: at,
- text: text
- };
- },
- incomplete = function(m) {
- throw {
- name: 'IncompleteJson',
- message: m,
- at: at,
- text: text
- };
- },
- next = function (c) {
- // If a c parameter is provided, verify that it matches the current character.
- if (c && c !== ch) {
- m = ("Expected '" + c + "' instead of '" + ch + "'");
- if (!ch) incomplete(m);
- else error(m);
- }
- // Get the next character. When there are no more characters,
- // return the empty string.
- ch = text.charAt(at);
- at += 1;
- return ch;
- },
- number = function () {
- // Parse a number value.
- var number,
- string = '';
- if (ch === '-') {
- string = '-';
- next('-');
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- if (ch === '.') {
- string += '.';
- while (next() && ch >= '0' && ch <= '9') {
- string += ch;
- }
- }
- if (ch === 'e' || ch === 'E') {
- string += ch;
- next();
- if (ch === '-' || ch === '+') {
- string += ch;
- next();
- }
- while (ch >= '0' && ch <= '9') {
- string += ch;
- next();
- }
- }
- number = +string;
- if (!isFinite(number)) {
- error("Bad number");
- } else {
- return number;
- }
- },
- string = function () {
- // Parse a string value.
- var hex,
- i,
- string = '',
- uffff;
- // When parsing for string values, we must look for " and \ characters.
- if (ch === '"') {
- while (next()) {
- if (ch === '"') {
- next();
- return string;
- } else if (ch === '\\') {
- next();
- if (ch === 'u') {
- uffff = 0;
- for (i = 0; i < 4; i += 1) {
- hex = parseInt(next(), 16);
- if (!isFinite(hex)) {
- break;
- }
- uffff = uffff * 16 + hex;
- }
- string += String.fromCharCode(uffff);
- } else if (typeof escapee[ch] === 'string') {
- string += escapee[ch];
- } else {
- break;
- }
- } else {
- string += ch;
- }
- }
- }
- if (ch === '') incomplete("Bad string");
- else error("Bad string");
- },
- white = function () {
- // Skip whitespace.
- while (ch && ch <= ' ') {
- next();
- }
- },
- word = function () {
- // true, false, or null.
- switch (ch) {
- case 't':
- next('t');
- next('r');
- next('u');
- next('e');
- return true;
- case 'f':
- next('f');
- next('a');
- next('l');
- next('s');
- next('e');
- return false;
- case 'n':
- next('n');
- next('u');
- next('l');
- next('l');
- return null;
- }
- error("Unexpected '" + ch + "'");
- },
- value, // Place holder for the value function.
- array = function () {
- // Parse an array value.
- var array = [];
- if (ch === '[') {
- next('[');
- white();
- if (ch === ']') {
- next(']');
- return array; // empty array
- }
- while (ch) {
- array.push(value());
- white();
- if (ch === ']') {
- next(']');
- return array;
- }
- next(',');
- white();
- }
- }
- if (ch === '') incomplete("Bad array");
- else error("Bad array");
- },
- object = function () {
- // Parse an object value.
- var key,
- object = {};
- if (ch === '{') {
- next('{');
- white();
- if (ch === '}') {
- next('}');
- return object; // empty object
- }
- while (ch) {
- key = string();
- white();
- next(':');
- if (Object.hasOwnProperty.call(object, key)) {
- error('Duplicate key "' + key + '"');
- }
- object[key] = value();
- white();
- if (ch === '}') {
- next('}');
- return object;
- }
- next(',');
- white();
- }
- }
- if (ch === '') incomplete("Bad object");
- else error("Bad object");
- };
- value = function () {
- // Parse a JSON value. It could be an object, an array, a string, a number,
- // or a word.
- white();
- switch (ch) {
- case '{':
- return object();
- case '[':
- return array();
- case '"':
- return string();
- case '-':
- return number();
- default:
- return ch >= '0' && ch <= '9' ? number() : word();
- }
- };
- // Return the json_parse function. It will have access to all of the above
- // functions and variables.
- var try_parse = function (source, reviver) {
- var result;
- text = source;
- at = 0;
- ch = ' ';
- result = value();
- white();
- //if (ch) {
- // error("Syntax error");
- //}
- // If there is a reviver function, we recursively walk the new structure,
- // passing each name/value pair to the reviver function for possible
- // transformation, starting with a temporary root object that holds the result
- // in an empty key. If there is not a reviver function, we simply return the
- // result.
- return typeof reviver === 'function' ? (function walk(holder, key) {
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.prototype.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return [reviver.call(holder, key, value), at-1];
- }({'': result}, '')) : [result, at-1];
- };
- return function(source, reviver) {
- if (source === '') return [undefined, 0];
- try {
- return try_parse(source, reviver);
- } catch (e) {
- if (e.name === "IncompleteJson") return [undefined, 0];
- else throw e;
- }
- };
- }());
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement