2021年6月28日 星期一

[json, ajv, post, xhr, html] How to post JSON data to server using XMLHttpRequest, React, Express and AJV

How to post JSON data to server using XMLHttpRequest, React, Express and AJV

井民全, Jing, mqjing@gmail.com


This document will show you how to post JSON data to the server using XMLHttpRequest, React, Express, and using AJV to validate the JSON schema at the server site. 

A client can easily POST JSON data to the server by using XMLHttpRequest with 'content-type' as 'application/json'. At the server, An application/json parser was adopted to extract the JSON information from received data (req.body property).  We knew that the JSON data from the client may be invalid in the predefined schema. Here, I use Ajv to handle this.

Fig. Test Result.

Github

Quick

JSON schema validator

const Ajv = require("ajv/dist/jtd")

const ajv = new Ajv() // options can be passed, e.g. {allErrors: true}


const schema = {

        properties: {

            num: {type: "int32"}, 

            msg: {type: "string"}

        },

}



const validate = ajv.compile(schema)


     // Test validator

      console.log('should be valid', validate({num: 0, msg: 'world'})) // ok

           interface Status  {

           num: number;

           msg: string;

      }

       let statusMy2:Status = {num: 0, msg: 'world'};

      console.log('should be valid', validate(statusMy2)) 

      console.log('should be valid req.body', validate(req.body))    // very the req.body




Client

var xhr = new XMLHttpRequest;

xhr.open("POST", url);

xhr.setRequestHeader('Content-Type', 'application/json');   

xhr.send(JSON.stringify({"num":0,"msg":"init"})); 


Server

router.use(bodyParser.json({type: 'application/json'})); 


router.post('/status_json', function(req:Request, res:Response, next) {


    // Verify the data from client

    if(!validate(req.body)){

        let strMsg:string = '[server] ERROR. validate(req.body).\nReceived:' + JSON.stringify(req.body);

        console.log(strMsg);

        console.log('v error = ' + JSON.stringify(validate.errors));

        res.send(strMsg)

        return;

    }

    console.log('[server] JSON schema: ok.');


}


Detail

Client

interface Status  {

  num: number;

  msg: string;

}


async function TestPostJSON(){

  console.log('TestPostJSON');

  const url:string = urlJSONResourceApi;

  let statusMe:Status = {num: 0, msg: 'init'};


  var xhr = new XMLHttpRequest;

  xhr.open("POST", url);

  xhr.setRequestHeader('Content-Type', 'application/json');  

  xhr.send(JSON.stringify(statusMe));  

  // xhr.send(JSON.stringify({"num123":0,"msg":"init"})); // will failure the JSON schema test


  console.log('[client] sent: statusMe = ' + JSON.stringify(statusMe));

  xhrEventHandle(xhr);

}



Server

import express, {Request, Response} from 'express';


interface Status  {

    num: number;

    msg: string;

}


let status:Status = {num: 0, msg: 'init'};

var router = express.Router();

var bodyParser  = require('body-parser');


// api: data/status_json

// router.post('/status_json', function(req:Request, res:Response, next) {

router.post('/status_json', bodyParser.json(), function(req:Request, res:Response, next) {

    console.log('[server] received, header = ' + JSON.stringify(req.headers))

    console.log('[server] body = ' + req.body);

    console.log('[server] Content-Type = ' + req.get('content-type'));


    // Step 2: Check JSON

    const Ajv = require("ajv/dist/jtd")

    const ajv = new Ajv() // options can be passed, e.g. {allErrors: true}


    const schema = {

        properties: {

            num: {type: "int32"}, 

            msg: {type: "string"}

        },

    }


    const validate = ajv.compile(schema)

    // Test validator

      console.log('should be valid', validate({num: 0, msg: 'world'})) // ok

      let statusMy2:Status = {num: 0, msg: 'world'};

      console.log('should be valid', validate(statusMy2)) 

      console.log('should be valid req.body', validate(req.body)) 


    if(!validate(req.body)){

        let strMsg:string = '[server] ERROR. validate(req.body).\nReceived:' + JSON.stringify(req.body);

        console.log(strMsg);

        console.log('v error = ' + JSON.stringify(validate.errors));

        res.send(strMsg)

        return;

    }

    console.log('[server] JSON schema: ok.');

   


    let statusMy:Status = req.body as Status;


    // Step 3: Access data

    for (var prop in statusMy) {

        if (statusMy.hasOwnProperty(prop)) {

            console.log('prop = ' + prop + ', value = ' + statusMy[prop as keyof Status]);

        }

    }


    // Step 4: Response to client

    let strMsg:string = '[server] response. statusMy = ' + JSON.stringify(statusMy);

    console.log(strMsg);

    res.send(strMsg)

});





module.exports = router;



Result


Reference

  1. https://ajv.js.org/