docs: function(fields, array_in, data_out) {
          var results = [],
              len = fields.length,
              i, j,
              field, key, locator, path, parser, val,
              simplePaths = [], complexPaths = [], fieldParsers = [],
              result, record;
  
          // First collect hashes of simple paths, complex paths, and parsers
          for (i=0; i<len; i++) {
              field = fields[i]; // A field can be a simple string or a hash
              key = field.key || field; // Find the key
              locator = field.locator || key; // Find the locator
  
              // Validate and store locators for later
              path = SchemaJSON.getPath(locator);
              if (path) {
                  if (path.length === 1) {
                      simplePaths.push({
                          key : key,
                          path: path[0]
                      });
                  } else {
                      complexPaths.push({
                          key    : key,
                          path   : path,
                          locator: locator
                      });
                  }
              } else {
                  //Y.log("Invalid key syntax: " + key, "warn", "dataschema-json");
              }
  
              // Validate and store parsers for later
              //TODO: use Y.DataSchema.parse?
              parser = (isFunction(field.parser)) ?
                  field.parser :
                  null;//Y.Parsers[field.parser + ''];
  
              if (parser) {
                  fieldParsers.push({
                      key   : key,
                      parser: parser
                  });
              }
          }
  
          // Traverse list of array_in, creating records of simple fields,
          // complex fields, and applying parsers as necessary
          for (i=array_in.length-1; i>=0; --i) {
              record = {};
              result = array_in[i];
              if(result) {
                  // Cycle through complexLocators
                  for (j=complexPaths.length - 1; j>=0; --j) {
                      path = complexPaths[j];
                      val = SchemaJSON.getLocationValue(path.path, result);
                      if (val === undefined) {
                          val = SchemaJSON.getLocationValue([path.locator], result);
                          // Fail over keys like "foo.bar" from nested parsing
                          // to single token parsing if a value is found in
                          // results["foo.bar"]
                          if (val !== undefined) {
                              simplePaths.push({
                                  key:  path.key,
                                  path: path.locator
                              });
                              // Don't try to process the path as complex
                              // for further results
                              complexPaths.splice(i,1);
                              continue;
                          }
                      }
  
                      record[path.key] = this.parse(
                          (SchemaJSON.getLocationValue(path.path, result)), path);
                  }
  
                  // Cycle through simpleLocators
                  for (j = simplePaths.length - 1; j >= 0; --j) {
                      path = simplePaths[j];
                      // Bug 1777850: The result might be an array instead of object
                      record[path.key] = this.parse(
                          ((result[path.path] === undefined) ?
                              result[j] : result[path.path]), path);
                  }
  
                  // Cycle through fieldParsers
                  for (j=fieldParsers.length-1; j>=0; --j) {
                      key = fieldParsers[j].key;
                      record[key] = fieldParsers[j].parser.call(this, record[key]);
                      // Safety net
                      if (record[key] === undefined) {
                          record[key] = null;
                      }
                  }
                  results[i] = record;
              }
          }
          data_out.results = results;
          return data_out;
      }