Search code examples
javascriptnode.jsvalidationserializationajv

validate and transform a field value using ajv in nodejs


I want to validate and change field json_data.childOrder.Order.triggerPrice using ajv. But my customKeyword function is never called.

I want to update it to 10% of json_data.ltp

I tried to read the documentation but its not very clear how to do this. And moany examples on stackoverflow are referring to old version of ajv library.

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

const OrderSchema = {
    type: 'object',
    properties: {
        childOrder: {
            type: 'object',
            additionalProperties: true,
            properties: {
                Order: {
                    type: 'object',

                    additionalProperties: true,

                    properties: {
                        qty: {
                            type: 'string'
                        },
                        triggerPrice: {
                            type: 'number'
                        }

                    },
                    required: ['triggerPrice', 'qty']

                }

            }
        }

    },
    additionalProperties: true

}

json_data = {
    childOrder: {
        Order: {
            buy: 'true',
            orderType: '3',
            price: 3999,
            qty: '10',
            triggerPrice: 3400
        }
    },
    duration: 'DAY',
    ltp: 3435,
    orderType: '3',
    price: 0,
    product: 'wood',
    qty: '10',
}

ajv.addKeyword({
    keyword: 'triggerPrice',
    type: 'number',
    compile: (a, b) => {
        // logic to transaform trigger price
        console.log(a, b)
    }
})
const validateOrder = ajv.compile(OrderSchema)

const _validate = validateOrder(json_data)

are there any other alternate ways of doing validatin in nodejs like there are in python marshmallow and django DRF.


Solution

  • In order for your custom keyword validation to work, you need to modify the compile function to return a data validation function instead of actually running validation logic:

    ajv.addKeyword({
      keyword: "triggerPrice",
      type: "number",
      compile: (schema, parentSchema, it) => {
        const validate = (data, dataPath) => {
          // run your validation logic here and return true/false if data is valid
          return true;
        };
        return validate;
      },
    });
    

    In addition, in order for the keyword to be applied to a property in your schema, you need to "flag" this property with the custom keyword (having the same name doesn't do anything...): note triggerPrice: true was added to the triggerPrice property in the schema object

    const OrderSchema = {
      type: "object",
      properties: {
        childOrder: {
          type: "object",
          additionalProperties: true,
          properties: {
            Order: {
              type: "object",
              additionalProperties: true,
              properties: {
                qty: {
                  type: "string",
                },
                triggerPrice: {
                  type: "number",
                  triggerPrice: true, // add custom validation keyword
                },
              },
              required: ["triggerPrice", "qty"],
            },
          },
        },
      },
      additionalProperties: true,
    };