简体   繁体   中英

Node JS cannot read property 'length' of undefined

I am attempting to run a .js file that will allow me to import a JSON file into Parse.com using REST API. The issue is that when I run it I get this error:

TypeError: Cannot read property 'length' of undefined
    at importFromJson 

Here is the .js in its entirety. Can someone please help me out? I'm pretty new to .js and REST API, having to do this due to Parse messing up and removing import feature.

var PARSE_APPLICATION_ID = 'APPID';
var PARSE_REST_API_KEY = 'RESTKEY';

var JSON_FILE_PATH = '/Users/candacebrassfield/Documents/JacksonParse/cloud/JacksonDirectory.json'; // Path to JSON file to import
var IMPORTED_CLASS_NAME = 'JacksonDirectory2'; // Class to import
var POINTING_CLASS_NAME = 'JacksonDirectory'; // Class with pointers to imported class
var POINTING_CLASS_PROPERTY = 'String'; // Name of pointer property

var request = require('request');
var fs = require('fs');

// Import objects from JSON to Parse
importFromJson(JSON_FILE_PATH, IMPORTED_CLASS_NAME, function(newObjectIds) {
    console.log('Successfully imported objects from JSON.');
    // Update objects from external Parse class pointing to imported objects
    updatePointingObjects(IMPORTED_CLASS_NAME, POINTING_CLASS_NAME, POINTING_CLASS_PROPERTY, newObjectIds, function() {
        console.log('Successfully updated pointing objects.');
    });
});


function importFromJson(jsonFilePath, importedClassName, callback) {
    // Store new objectIds associated to their original objectIds
    // Will be used to update pointers of other Parse classes
    var newObjectIds = {};

    // Read and parse JSON file
    var json = JSON.parse(fs.readFileSync(jsonFilePath, 'utf8'));

    // Delay requests with setTimeout to stay under Parse's limit
    delayedAsyncLoop(function(i, fnCallback) {
            // Loop
            var obj = json.results[i - 1];
            var originalObjectId = obj.objectId;
            // Create object using Parse REST API
            createObject(importedClassName, obj, function(newObj) {
                // Abort if request fails
                if (!newObj) process.exit(-1);
                // Associate the object's new objectId to its original objectId
                newObjectIds[originalObjectId] = newObj.objectId;
                fnCallback();
            });
        },
        json.results.length, // Iterations

        100, // Delay in milliseconds
        function() { // Done looping
            callback(newObjectIds);
        });
}

function updatePointingObjects(importedClassName, pointingClassName, pointingClassProperty, newObjectIds, callback) {
    // Get all objects from another Parse class that point to our imported class
    getAllPointingObjects(pointingClassName, pointingClassProperty, function(pointingObjects) {
        // Abort if request fails
        if (!pointingObjects) process.exit(-1);

        var nbObjectsToUpdate = pointingObjects.length;
        // Delay requests with setTimeout to stay under Parse's limit
        delayedAsyncLoop(function(i, fnCallback) {
                // Loop
                var pointingObject = pointingObjects[i - 1];
                var pointer = pointingObject[pointingClassProperty];
                if (!pointer || pointer.className != importedClassName) {
                    fnCallback();
                    nbObjectsToUpdate--;
                    if (!nbObjectsToUpdate) callback(); // Done updating pointing objects
                    return;
                }
                // Retrieve the new objectId each pointer should be updated with
                var originalObjectId = pointer.objectId;
                var newObjectId = newObjectIds[originalObjectId];
                if (!newObjectId) {
                    fnCallback();
                    nbObjectsToUpdate--;
                    if (!nbObjectsToUpdate) callback(); // Done updating pointing objects
                    return;
                }
                // Update pointer to the new objectId
                updatePointingObject(pointingClassName, pointingClassProperty, pointingObject.objectId, importedClassName, newObjectId, function() {
                    fnCallback();
                    nbObjectsToUpdate--;
                    if (!nbObjectsToUpdate) callback(); // Done updating pointing objects
                });
            },
            pointingObjects.length, // Iterations
            100 // Delay in milliseconds
        );
    });
}


function delayedAsyncLoop (fn, iterations, delay, callback) {
    (function loop (i, done) {
        setTimeout(function() {
            fn(i, function() {
                if (--i) {
                    // Keep looping
                    loop(i, done);
                } else {
                    // Loop done
                    if (done) done();
                }
            });
        }, delay)
    })(iterations, callback);
}

function createObject(className, object, callback) {
    delete object.objectId;
    delete object.createdAt;
    delete object.updatedAt;

    request({
        method: 'POST',
        url: 'https://api.parse.com/1/classes/' + className,
        headers: {
            'X-Parse-Application-Id': PARSE_APPLICATION_ID,
            'X-Parse-REST-API-Key': PARSE_REST_API_KEY,
            'Content-Type': 'application/json; charset=UTF-8'
        },
        body: JSON.stringify(object)
    }, function(error, response, body) {
        if (response.statusCode == 201) {
            var result = JSON.parse(body);

            object.objectId = result.objectId;
            object.createdAt = result.createdAt;
            object.updatedAt = result.updatedAt;

            console.log('Created ' + className + ' object with objectId ' + result.objectId);
            callback(object);
        } else {
            console.log('Error: ' + response.statusCode);
            console.log(body);
            callback();
        }
    });
}

function getAllPointingObjects(className, pointingProperty, callback) {
    getPointingObjectsRecursive([], className, pointingProperty, 0, null, callback)
}

function getPointingObjectsRecursive(allObjects, className, pointingProperty, skipNb, minCreatedAt, callback) {
    var whereObj = {};
    whereObj[pointingProperty] = {
        '$exists': true
    };
    if (minCreatedAt) {
        whereObj['createdAt'] = {
            '$gt': minCreatedAt
        };
    }
    var queryString = {
        'limit': 1000,
        'order': 'createdAt',
        'skip': skipNb,
        'where': JSON.stringify(whereObj)
    };

    request({
        method: 'GET',
        url: 'https://api.parse.com/1/classes/' + className,
        headers: {
            'X-Parse-Application-Id': PARSE_APPLICATION_ID,
            'X-Parse-REST-API-Key': PARSE_REST_API_KEY
        },
        qs: queryString
    }, function(error, response, body) {
        if (response.statusCode == 200) {
            var results = JSON.parse(body).results;
            Array.prototype.push.apply(allObjects, results);
            if (results.length == 1000) {
                // Keep fetching
                if (skipNb > 10000) {
                    minCreatedAt = results[999].createdAt;
                    skipNb = 0;
                }
                getPointingObjectsRecursive(allObjects, className, pointingProperty, skipNb+1000, minCreatedAt, callback);
            } else {
                // All objects fetched
                callback(allObjects);
            }
        } else {
            console.log('Error: ' + response.statusCode);
            console.log(body);
            callback();
        }
    });
}

function updatePointingObject(pointingClassName, pointingClassProperty, pointingObjectId, pointedClassName, pointedObjectId, callback) {
    var pointer = {
        "__type": "Pointer",
        "className": pointedClassName,
        "objectId": pointedObjectId
    };

    var requestBody = {};
    requestBody[pointingClassProperty] = pointer;

    request({
        method: 'PUT',
        url: 'https://api.parse.com/1/classes/' + pointingClassName + '/' + pointingObjectId,
        headers: {
            'X-Parse-Application-Id': PARSE_APPLICATION_ID,
            'X-Parse-REST-API-Key': PARSE_REST_API_KEY,
            'Content-Type': 'application/json; charset=UTF-8'
        },
        body: JSON.stringify(requestBody)
    }, function(error, response, body) {
        if (response.statusCode == 200) {
            console.log('Updated pointer of ' + pointingClassName + '/' + pointingObjectId + ' to ' + pointedObjectId);
            callback();
        } else {
            console.log('Error: ' + response.statusCode);
            console.log(body);
            callback();
        }
    });
}

Here is an edited version of the JSON file.

[  

   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   },
   {  
      "TELEPHONE NUMBER":"",
      "FAMILY NAMES":"",
      "STREET ADDRESS":"",
      "CITY, STATE, ZIP CODE":"",
      "E-MAIL ADDRESS":""
   }
]

Those blank ones were all at the bottom of the file, but removing them didn't fix anything.

The sample JSON has no results property, so json.results is undefined.

json.length will give you the number of iterations required.

JSON.parse("[{},{}]").length => 2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM