dataparser-json.js revision 6608a5406cae6b74c06f0a501e189d1fc173dc21
3909N/A * The DataParser utility provides a common configurable interface for widgets to 0N/A * parse a variety of data against a given schema. 0N/A * @module dataparser 0N/A * JSON subclass for the YUI DataParser utility. 0N/A * @extends DataParser.Base 0N/A ///////////////////////////////////////////////////////////////////////////// 2362N/A ///////////////////////////////////////////////////////////////////////////// 0N/A * Utility function converts JSON locator strings into walkable paths 0N/A * @param locator {String} JSON value locator. 0N/A * @return {String[]} Walkable path to data value. 0N/A // Strip the ["string keys"] and [1] array indexes 0N/A function (x,$1,$2) {keys[i]=$2;return '.@
'+(i++);}). 0N/A replace(/\[(\d+)\]/g, 0N/A function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@
'+(i++);}). 0N/A replace(/^\./,''); // remove leading dot 0N/A // Validate against problematic characters. 0N/A if (!/[^\w\.\$@]/.test(locator)) { 0N/A path = locator.split('.
'); 0N/A for (i=path.length-1; i >= 0; --i) { 0N/A if (path[i].charAt(0) === '@
') { 1676N/A path[i] = keys[parseInt(path[i].substr(1),10)]; 0N/A Y.log("Invalid locator: " + locator, "error", this.toString()); 0N/A * Utility function to walk a path and return the value located there. 0N/A * @param path {String[]} Locator path. 0N/A * @param data {String} Data to traverse. 0N/A * @return {Object} Data value at location. 0N/A walkPath: function (path, data) { 0N/A data = data[path[i]]; 0N/A * Overriding parse method traverses JSON data according to given schema. 0N/A * @param schema {Object} Schema to parse against. 0N/A * @param data {Object} Data to parse. 0N/A * @return {Object} Schema-parsed data. 0N/A _parse: function(schema, data) { 0N/A var data_in = (data.responseText && Y.JSON.parse(data.responseText)) || data, 0N/A data_out = {results:[],meta:{}}; 0N/A if(LANG.isObject(data_in) && schema) { 0N/A // Parse results data 0N/A data_out = this._parseResults(schema, data_in, data_out); 0N/A if(LANG.isObject(schema.metaFields)) { 0N/A data_out = this._parseMeta(schema.metaFields, data_in, data_out); 0N/A Y.log("JSON data could not be parsed: " + Y.dump(data_in), "error", this.toString()); 0N/A data_out.error = true; 0N/A * Schema-parse list of results from full data 0N/A * @method _parseResults 0N/A * @return {Array} Array of results. 0N/A _parseResults: function(schema, data_in, data_out) { 0N/A if(schema.resultsList) { 0N/A path = DPJSON.buildPath(schema.resultsList); 0N/A results = DPJSON.walkPath(path, data_in); 0N/A if (results === undefined) { 0N/A if(LANG.isArray(schema.fields)) { 0N/A if(LANG.isArray(schema.fields)) { 0N/A results = this._filterFieldValues(schema.fields, results); 0N/A Y.log("JSON data could not be parsed: " + Y.dump(data_in), "error", this.toString()); 0N/A data_out.error = true; 0N/A data_out.results = results; 1676N/A * Schema-parse field data out of list of full results 1676N/A * @method _filterFieldValues 1676N/A * @return {Array} Array of field-filtered results. 1676N/A _filterFieldValues: function(fields, results) { 1676N/A simplePaths = [], complexPaths = [], fieldParsers = [], 0N/A // First collect hashes of simple paths, complex paths, and parsers 0N/A for (i=0; i<len; i++) { 1676N/A field = fields[i]; // A field can be a simple string or a hash 1676N/A key = field.key || field; // Find the key 1676N/A // Validate and store locators for later 1676N/A path = DPJSON.buildPath(key); 1676N/A simplePaths[simplePaths.length] = {key:key, path:path[0]}; 1676N/A complexPaths[complexPaths.length] = {key:key, path:path}; 1676N/A Y.log("Invalid key syntax: " + key, "warn", this.toString()); 3480N/A // Validate and store parsers for later 3480N/A parser = (LANG.isFunction(field.parser)) ? field.parser : Y.DataParser[field.parser+'']; 1676N/A fieldParsers[fieldParsers.length] = {key:key, parser:parser}; 1676N/A // Traverse list of results, creating records of simple fields, 1676N/A // complex fields, and applying parsers as necessary 0N/A for (i=results.length-1; i>=0; --i) { 0N/A result = results[i]; 0N/A // Cycle through simpleLocators 0N/A for (j=simplePaths.length-1; j>=0; --j) { 0N/A // Bug 1777850: The result might be an array instead of object 0N/A record[simplePaths[j].key] = 0N/A LANG.isUndefined(result[simplePaths[j].path]) ? 0N/A result[j] : result[simplePaths[j].path]; 0N/A // Cycle through complexLocators 0N/A for (j=complexPaths.length - 1; j>=0; --j) { 0N/A record[complexPaths[j].key] = DPJSON.walkPath(complexPaths[j].path, result); 0N/A // Cycle through fieldParsers 0N/A for (j=fieldParsers.length-1; j>=0; --j) { 0N/A key = fieldParsers[j].key; 0N/A record[key] = fieldParsers[j].parser(record[key]); 0N/A if (LANG.isUndefined(record[key])) { 0N/A data_out[i] = record; 0N/A * Parses results data according to schema 0N/A * @method _parseMeta 0N/A * @return {Object} Schema-parsed meta data. _parseMeta: function(metaFields, data_in, data_out) { if (metaFields.hasOwnProperty(key)) { path = DPJSON.buildPath(metaFields[key]); data_out.meta[key] = DPJSON.walkPath(path, data_in); Y.mix(DPJSON, Y.DataParser.Base);