Defining a Mongoose schema from a JSON file

2020-07-26 07:11发布

问题:

I want to define my mongoose schema from JSON file. This is my JSON file structure:

   {    
        "default": [
            {
                "item": "productTitle",
                "label": "Product Title",
                "note": "e.g Samsung GALAXY Note 4",
                "type": "text",
                "required": "Product Name cannot be blank..."
            },
            {
                "item": "productCode",
                "label": "Product Code",
                "type": "text",
                "required": "Product Code cannot be blank..."
            }    
        ]}

This is my node.js model:

// Load the module dependencies
var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var fs = require('fs');
var file = __dirname + '/product.server.model.json';

// Read the json file
fs.readFile(file, 'utf8', function (err, data) {

data = JSON.parse(data);

var productJson = {};
for(var  i = 0; i < data.default.length; i++) {

    productJson[data.default[i].slug] = {
        type: 'String',
        required: data.default[i].required,
        default: '',
        trim: true
    }

}

});

// Define a new 'ProductSchema'
var ProductSchema = new Schema(
   // Here I want to put JSON Data 'productJson'
);

// Create the 'Product' model out of the 'ProductSchema'
mongoose.model('Product', ProductSchema);    

I tried every possible way to define mongoose schema from JSON data 'productJson'. But unless I pre-define my mongoose schema, it is not working. Is there any way to define mongoose schema from JSON data in my model? Any suggestion please?

回答1:

fs.readFile is an asynchronous function which means that it returns immediately and then later provides its results to the caller via the callback function that you provide as the third parameter.

As such, you need to hold off on using productJson until its populated within that callback. That means moving your schema and model creation inside the callback as well.

fs.readFile(file, 'utf8', function (err, data) {

    data = JSON.parse(data);

    var productJson = {};
    for(var  i = 0; i < data.default.length; i++) {

        // Changed .slug to .item here as I don't see slug in the JSON
        productJson[data.default[i].item] = {
            type: 'String',
            required: data.default[i].required,
            default: '',
            trim: true
        }
    }

    // Define a new 'ProductSchema'
    var ProductSchema = new Schema(productJson);

    // Create the 'Product' model out of the 'ProductSchema'
    mongoose.model('Product', ProductSchema);
});

Another alternative you can use here is to use the synchronous fs.readFileSync method to read the file instead. This is helpful in startup/initialization cases like this where your application as a whole shouldn't proceed until this file is processed.

var data = fs.readFileSync(file, 'utf8');
data = JSON.parse(data);

var productJson = {};
for(var  i = 0; i < data.default.length; i++) {

    // Changed .slug to .item here as I don't see slug in the JSON
    productJson[data.default[i].item] = {
        type: 'String',
        required: data.default[i].required,
        default: '',
        trim: true
    }
}

// Define a new 'ProductSchema'
var ProductSchema = new Schema(productJson);

// Create the 'Product' model out of the 'ProductSchema'
mongoose.model('Product', ProductSchema);