Validating JSON in MCS

I was working with a customer the other day, trouble shooting an API that did not seem to be working when it was accessed by a MAX application. When he tested the API in MCS, everything worked fine. When he accessed that same API call from MAX, the list control was empty and the message "No data found" was displayed instead.
 
Fortunately, this customer noticed a small discrepancy between the JSON that was being returned by the API and the expected format of the JSON as specified by the schema. The API's schema for the returned JSON value was different than the actual return value and that was the root of the problem.
 

MCS Does Not Validate Your Data

By default, MCS does not validate any of the data that you pass through it. Developers sometimes assume that since MCS allows you to specify the schema, or limits | patterns | ranges on arguments, that MCS is validating these value. It does not. You can see this for yourself by test the HelloValidation API, which specified a 4 digit number in the simple greeting request. Use a 2 digit number instead and MCS will happily provide you with the example data.
 
There are two main reasons for the lack of automatic validation:
  1. Validation takes time and would slow down service response times.
  2. If you create a REST service that can take multiple request types and provides multiple response types (application/json, application/x-www-form-urlencoded or multipart/form-data) automating the validation of the payloads is nearly impossible.
However, as developers we know that slower response times are worth the trouble when we are creating new services. In the development phase we need visibility into how the services are running, not execution speed. Fortunately, MCS and Node.js do allow for validation and you can turn it on an off in your custom code.
 

Adding Validation to Your MCS Code

Adding validation to your code requires a few steps. The first thing you need is your API. I have create a RAML file for my sample API and you can download it and use it to create the same service that I am using for this blog entry. I named the API HelloValidation.
 
 
Now you need a JSON validator package. There are several out there but I chose the "jsonschema" package from nam because it seemed easy to use. Please note that I did not do an exhaustive (or even cursory) examination of all available JSON validators so my use of jsonschema is not an endorsement in any way, just a handy example. Feel free to substitute with the validator of your choice. You can see the main page for jsonchema here.
 
From MCS download the javascript scaffold for the HelloValidation service and unzip it onto your local hard drive for editing.
 
Open a command window and navigate to the directory that contains your HelloValidation service.
 
Type in the following command

npm install jsonschemma

Once the installation is complete, you will see a node_modules directory. We now need to make your code aware of the existence of this package. Open up the package.json file and the package-lock.json file and compare them. Update the package.json file so that it looks like the following (assuming the version number of jsonschema hasn't changed since I wrote this).
 
{ "name": "hellovalidation",
  "version": "1.0",
  "description": "Provide a validated greeting to the caller",
  "main": "hellovalidation.js",
  "oracleMobile": {
    "dependencies": {
    "apis": {},
    "connectors": {} }
  },
  "dependencies": {
    "jsonschema": {
    "version": "1.1.1",
    "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.1.1.tgz",
    "integrity": "sha1-PO3o4+QR03eHLu+8n98mODy8Ptk="
    }
  }
}
 
Next you need to modify the code for the GET method to provide a validated response. We can also use this code to test invalid requests and responses. Open the hellovalidation.js file. The first thing we want to do is to add some validation to the {id}
 
module.exports = function(service) {
   var validationActive = true;
   /**
    *  The file samples.txt in the archive that this file was packaged with
    *  contains some example code.
    */
   service.get('/mobile/custom/HelloValidation/simplegreeting', function(req,res) {
   // Get the "id" query parameter as a number. It is a string by default
   var id = parseInt(req.query.id);
   if(validationActive) {
      // Initialize our validator object
      var Validator = require('jsonschema').Validator;
      var v = new Validator();
      // Create a schema for numeric values between 1000 and 9999
      var idSchema = {"type": "number", "minimum": 1000, "maximum": 9999};
      console.info("validating an id with the value: " + id);
      // Validate the query parameter
      var vRes = v.validate(id, idSchema);
      if(vRes.errors.length > 0) {
         // There was an error in the ID. Handle it
         console.info("bad ID: " + id);
      } else {
         // Validation passed.
         console.info("good ID: " + id);
      }
   console.info(vRes); // Write the validation results to the log.
   }
   // Create our result object
   var result = { "simplegreeting" : "Hello John" };
   if(validationActive) {
      // Now create our result schema
      var resultSchema = {
         "$schema": "http://json-schema.org/draft-04/schema#",
         "definitions": {},
         "id": "http://oracle.com/simplegreeting",
         "properties": {
         "simplegreeting": {
            "id": "/properties/simplegreeting",
            "type": "string"
         }
     ,
      "type": "object"
      }
      console.info(v.validate(result, resultSchema));
   }
 
   var statusCode = 200; // Success
   res.status(statusCode).send(result);
   });
};
 
Note the line near the top of the code:
var validationActive = true;
 
This is our switch to turning validation on and off. When you move the code to production, this allows you to quickly and easily turn off validation. Of course, you may wish to leave validation turned on in production, especially if your services are being called by partners or the public. It is entirely possible that they may send bad query parameters or payloads, accidentally or deliberately.
 
Naturally in production code you would want to send errors back to the caller, either in the header or in the body of the response. This example is not meant to show coding best practices, only to show how easy it is to add JSON validation to your projects

Author