javascript - Node JS 无法读取未定义的属性 'length'

标签 javascript json node.js parse-platform

我正在尝试运行一个 .js 文件,该文件允许我使用 REST API 将 JSON 文件导入 Parse.com。问题是当我运行它时出现此错误:

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

这是完整的 .js。有人可以帮帮我吗?我是 .js 和 REST API 的新手,由于 Parse 困惑和删除导入功能而不得不这样做。

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();
        }
    });
}

这是 JSON 文件的编辑版本。

[  

   {  
      "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":""
   }
]

那些空白的都在文件的底部,但是删除它们并没有解决任何问题。

最佳答案

示例 JSON 没有 results 属性,因此 json.results 未定义。

json.length 将为您提供所需的迭代次数。

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

关于javascript - Node JS 无法读取未定义的属性 'length',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37741997/

相关文章:

javascript - 如何在 Pixi.js 中绘制 Sprite 板?

javascript - 动态加载 json 文件 - javascript

python - 使用 Pandas 读取 JSON 时出现“预期的字符串或 Unicode”

设置 contentType 时 jquery ajax 不工作

javascript - Expressjs - 所有路由都是 404

javascript - 想在django中使用chartjs绘制数据

node.js - 在 Express 和 node.js 的路由设置中使用 dynamicHelpers

javascript - 如何将多个 JSON 对象用于单个 NodeJS/Jade 合并

javascript - 使用 Javascript 或 Nodejs 连接到 Temenos T24

java - 使用 HttpClient 将 URL 中的 JSON 查询字符串发送到 Web 服务 (Java)