node.jsjsonmongodbmongoose

Initialize Mongoose Schema from JSON


I have some JSON data that is being POST'd via an HTTP body that looks like:

{
  orderList: [
    { product: [Object], quantity: '1' },
    { product: [Object], quantity: '1' },
    { product: [Object], quantity: '1' },
    { product: [Object], quantity: '1' }
  ],
  user: {
    name: { first: 'John', middle: 'Jay', last: 'Dent' },
    address: {
      street1: '1 Easy Street',
      street2: '',
      city: 'Los Angeles',
      state: 'California',
      zip: '12345'
    },
    email: 'john@nocantack.com',
    phone: '123 456-7890',
    isAdmin: false
  },
  date: '2019-10-28T20:30:54.914Z',
  totalCost: 1149.78,
  totalTax: 10.8
}

I am trying to generate a schema from this JSON and something is not right because it throws an error. Right now I am populating the Mongoose Schema like

  const newOrder = new Order(req.body);

and then attempting to write to the MongoDB database like

  newOrder.save()
   .then(() => res.json('Order added!'))
   .catch(err => res.status(400).json(`Error: ${err}`));

The save is throwing the exception that is being caught and returning 400.

As best as I can tell the problem seems to be that the 'orderList' field shown above is an array of two fields one an object and one a number (shown as keys 'product' and 'quantity' respectively). The object I describe in the Mongoose Schema. The problem is that is essentially an "array of objects" doesn't seem to get properly turned into the Mongoose Schema. What else do I need to do in addition/instead of just passing the JSON to the constructor of the Schema?


Solution

  • Here are 2 ways you can produce a mongoose schema from JSON:

    1) (The hard way) Use a recursive function to loop over your JSON object and replace the values with its typeof value. Something like:

    req.body.orderList.product = typeof req.body.orderList.product
    

    2) (The easy way) Use a module like generate-schema which provides a function that can generate a Mongoose schema from JSON. Install it via npm (npm install generate-schema) and then implement like so:

    const generateSchema = require('generate-schema');
    
    let jsonData = req.body;
    
    let MongooseSchema = generateSchema.mongoose(jsonData);
    
    

    mongooseSchema now contains your schema. Running console.log(mongooseSchema) returns:

    { orderList: { type: [ 'Mixed' ] },
      user:
       { name: { first: [Object], middle: [Object], last: [Object] },
         address:
          { street1: [Object],
            street2: [Object],
            city: [Object],
            state: [Object],
            zip: [Object] },
         email: { type: 'String' },
         phone: { type: 'String' },
         isAdmin: { type: 'Boolean' } },
      date: { type: 'Date' },
      totalCost: { type: 'Number' },
      totalTax: { type: 'Number' } }
    

    You can then do the following:

    let mongoose = require('mongoose')
    let NewOrder = mongoose.model('Order', MongooseSchema)
    
    let newOrder = new NewOrder(req.body)
    
    newOrder.save()
      .then(() => res.json('Order added!'))
      .catch(err => res.status(400).json(`Error: ${err}`));