PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/yui/3.0.0b1/dataschema/dataschema-json.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 287 lines | 256 code | 5 blank | 26 comment | 1 complexity | c71129808dc295ea12323750e1c7babf MD5 | raw file
  1. YUI.add('dataschema-json', function(Y) {
  2. /**
  3. * Provides a DataSchema implementation which can be used to work with JSON data.
  4. *
  5. * @module dataschema
  6. * @submodule dataschema-json
  7. */
  8. /**
  9. * JSON subclass for the DataSchema Utility.
  10. * @class DataSchema.JSON
  11. * @extends DataSchema.Base
  12. * @static
  13. */
  14. var LANG = Y.Lang,
  15. SchemaJSON = {
  16. /////////////////////////////////////////////////////////////////////////////
  17. //
  18. // DataSchema.JSON static methods
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. /**
  22. * Utility function converts JSON locator strings into walkable paths
  23. *
  24. * @method DataSchema.JSON.getPath
  25. * @param locator {String} JSON value locator.
  26. * @return {String[]} Walkable path to data value.
  27. * @static
  28. */
  29. getPath: function(locator) {
  30. var path = null,
  31. keys = [],
  32. i = 0;
  33. if (locator) {
  34. // Strip the ["string keys"] and [1] array indexes
  35. locator = locator.
  36. replace(/\[(['"])(.*?)\1\]/g,
  37. function (x,$1,$2) {keys[i]=$2;return '.@'+(i++);}).
  38. replace(/\[(\d+)\]/g,
  39. function (x,$1) {keys[i]=parseInt($1,10)|0;return '.@'+(i++);}).
  40. replace(/^\./,''); // remove leading dot
  41. // Validate against problematic characters.
  42. if (!/[^\w\.\$@]/.test(locator)) {
  43. path = locator.split('.');
  44. for (i=path.length-1; i >= 0; --i) {
  45. if (path[i].charAt(0) === '@') {
  46. path[i] = keys[parseInt(path[i].substr(1),10)];
  47. }
  48. }
  49. }
  50. else {
  51. }
  52. }
  53. return path;
  54. },
  55. /**
  56. * Utility function to walk a path and return the value located there.
  57. *
  58. * @method DataSchema.JSON.getLocationValue
  59. * @param path {String[]} Locator path.
  60. * @param data {String} Data to traverse.
  61. * @return {Object} Data value at location.
  62. * @static
  63. */
  64. getLocationValue: function (path, data) {
  65. var i = 0,
  66. len = path.length;
  67. for (;i<len;i++) {
  68. if(!LANG.isUndefined(data[path[i]])) {
  69. data = data[path[i]];
  70. }
  71. else {
  72. data = undefined;
  73. break;
  74. }
  75. }
  76. return data;
  77. },
  78. /**
  79. * Applies a given schema to given JSON data.
  80. *
  81. * @method apply
  82. * @param schema {Object} Schema to apply.
  83. * @param data {Object} JSON data.
  84. * @return {Object} Schema-parsed data.
  85. * @static
  86. */
  87. apply: function(schema, data) {
  88. var data_in = data,
  89. data_out = {results:[],meta:{}};
  90. // Convert incoming JSON strings
  91. if(!LANG.isObject(data)) {
  92. try {
  93. data_in = Y.JSON.parse(data);
  94. }
  95. catch(e) {
  96. data_out.error = e;
  97. return data_out;
  98. }
  99. }
  100. if(LANG.isObject(data_in) && schema) {
  101. // Parse results data
  102. if(!LANG.isUndefined(schema.resultListLocator)) {
  103. data_out = SchemaJSON._parseResults(schema, data_in, data_out);
  104. }
  105. // Parse meta data
  106. if(!LANG.isUndefined(schema.metaFields)) {
  107. data_out = SchemaJSON._parseMeta(schema.metaFields, data_in, data_out);
  108. }
  109. }
  110. else {
  111. data_out.error = new Error("JSON schema parse failure");
  112. }
  113. return data_out;
  114. },
  115. /**
  116. * Schema-parsed list of results from full data
  117. *
  118. * @method _parseResults
  119. * @param schema {Object} Schema to parse against.
  120. * @param json_in {Object} JSON to parse.
  121. * @param data_out {Object} In-progress parsed data to update.
  122. * @return {Object} Parsed data object.
  123. * @static
  124. * @protected
  125. */
  126. _parseResults: function(schema, json_in, data_out) {
  127. var results = [],
  128. path,
  129. error;
  130. if(schema.resultListLocator) {
  131. path = SchemaJSON.getPath(schema.resultListLocator);
  132. if(path) {
  133. results = SchemaJSON.getLocationValue(path, json_in);
  134. if (results === undefined) {
  135. data_out.results = [];
  136. error = new Error("JSON results retrieval failure");
  137. }
  138. else {
  139. if(LANG.isArray(schema.resultFields) && LANG.isArray(results)) {
  140. data_out = SchemaJSON._getFieldValues(schema.resultFields, results, data_out);
  141. }
  142. else {
  143. data_out.results = [];
  144. error = new Error("JSON Schema fields retrieval failure");
  145. }
  146. }
  147. }
  148. else {
  149. error = new Error("JSON Schema results locator failure");
  150. }
  151. if (error) {
  152. data_out.error = error;
  153. }
  154. }
  155. return data_out;
  156. },
  157. /**
  158. * Get field data values out of list of full results
  159. *
  160. * @method _getFieldValues
  161. * @param fields {Array} Fields to find.
  162. * @param array_in {Array} Results to parse.
  163. * @param data_out {Object} In-progress parsed data to update.
  164. * @return {Object} Parsed data object.
  165. * @static
  166. * @protected
  167. */
  168. _getFieldValues: function(fields, array_in, data_out) {
  169. var results = [],
  170. len = fields.length,
  171. i, j,
  172. field, key, path, parser,
  173. simplePaths = [], complexPaths = [], fieldParsers = [],
  174. result, record;
  175. // First collect hashes of simple paths, complex paths, and parsers
  176. for (i=0; i<len; i++) {
  177. field = fields[i]; // A field can be a simple string or a hash
  178. key = field.key || field; // Find the key
  179. // Validate and store locators for later
  180. path = SchemaJSON.getPath(key);
  181. if (path) {
  182. if (path.length === 1) {
  183. simplePaths[simplePaths.length] = {key:key, path:path[0]};
  184. } else {
  185. complexPaths[complexPaths.length] = {key:key, path:path};
  186. }
  187. } else {
  188. }
  189. // Validate and store parsers for later
  190. //TODO: use Y.DataSchema.parse?
  191. parser = (LANG.isFunction(field.parser)) ? field.parser : Y.Parsers[field.parser+''];
  192. if (parser) {
  193. fieldParsers[fieldParsers.length] = {key:key, parser:parser};
  194. }
  195. }
  196. // Traverse list of array_in, creating records of simple fields,
  197. // complex fields, and applying parsers as necessary
  198. for (i=array_in.length-1; i>=0; --i) {
  199. record = {};
  200. result = array_in[i];
  201. if(result) {
  202. // Cycle through simpleLocators
  203. for (j=simplePaths.length-1; j>=0; --j) {
  204. // Bug 1777850: The result might be an array instead of object
  205. record[simplePaths[j].key] = Y.DataSchema.Base.parse(
  206. (LANG.isUndefined(result[simplePaths[j].path]) ?
  207. result[j] : result[simplePaths[j].path]), simplePaths[j]);
  208. }
  209. // Cycle through complexLocators
  210. for (j=complexPaths.length - 1; j>=0; --j) {
  211. record[complexPaths[j].key] = Y.DataSchema.Base.parse(
  212. (SchemaJSON.getLocationValue(complexPaths[j].path, result)), complexPaths[j] );
  213. }
  214. // Cycle through fieldParsers
  215. for (j=fieldParsers.length-1; j>=0; --j) {
  216. key = fieldParsers[j].key;
  217. record[key] = fieldParsers[j].parser(record[key]);
  218. // Safety net
  219. if (LANG.isUndefined(record[key])) {
  220. record[key] = null;
  221. }
  222. }
  223. results[i] = record;
  224. }
  225. }
  226. data_out.results = results;
  227. return data_out;
  228. },
  229. /**
  230. * Parses results data according to schema
  231. *
  232. * @method _parseMeta
  233. * @param metaFields {Object} Metafields definitions.
  234. * @param json_in {Object} JSON to parse.
  235. * @param data_out {Object} In-progress parsed data to update.
  236. * @return {Object} Schema-parsed meta data.
  237. * @static
  238. * @protected
  239. */
  240. _parseMeta: function(metaFields, json_in, data_out) {
  241. if(LANG.isObject(metaFields)) {
  242. var key, path;
  243. for(key in metaFields) {
  244. if (metaFields.hasOwnProperty(key)) {
  245. path = SchemaJSON.getPath(metaFields[key]);
  246. if (path && json_in) {
  247. data_out.meta[key] = SchemaJSON.getLocationValue(path, json_in);
  248. }
  249. }
  250. }
  251. }
  252. else {
  253. data_out.error = new Error("JSON meta data retrieval failure");
  254. }
  255. return data_out;
  256. }
  257. };
  258. Y.DataSchema.JSON = Y.mix(SchemaJSON, Y.DataSchema.Base);
  259. }, '@VERSION@' ,{requires:['json', 'dataschema-base']});