Using a JSON schema to validate a response body

In this next piece of code we're going to do two things:
  1. Define a JSON schema to describe the data we expect to receive when a client calls our API endpoint to create a new user. We want the data to be an object which always has a first_name and a last_name property. This object can optionally include an age property, and if it does, the value of that property must be an integer which is greater than or equal to 18.
  2. Use the user schema which we've defined to validate requests to our POST /user API endpoint.
// src/schemas/user.schema.js

const userSchema = {
    type: "object",
    required: ["first_name", "last_name", "age"],
    properties: {
        first_name: {
            type: "string",
            minLength: 1,
        last_name: {
            type: "string",
            minLength: 1,
        age: {
            type: "number",

export default userSchema;

// src/server.js

import validate from "./middleware/json-validator.js";

import userSchema from "./schemas/user.schema.js";
    validate({ body: userSchema }),
    function createUserRouteHandler(request, response, next) {
         * Normally you'd save the data you've received to a database,
         * but for this example we'll just send it back in the response.


(Example 2.7)
In the route definition above we're calling the validate() method from our Validator instance. We pass it an object telling it which request properties we want to validate, and what JSON schema we want to validate the value of each property against. It is configured to validate the body property of any requests to the POST /user endpoint against our userSchema JSON schema.
The validate() method compiles the JSON schema with Ajv, and then returns a middleware function which will be run every time a request is made to this endpoint. This middleware function will take care of running the validation which we've configured.
If the request body validates against our userSchema, the middleware function will call the next() Express function which was passed to it and our route handler function will be run. If Ajv returns a validation error, the middleware will call the next() Express function with an error object which has a validationErrors property containing an array of validation errors. Our route handler function will not be run. We'll look at where that error object gets passed to and how we can handle it in the next part of this book.