Empty values validation in json schema using AJV

18.2k views Asked by At

I am using Ajv for validating my JSON data. I am unable to find a way to validate empty string as a value of a key. I tried using pattern, but it does not throw appropriate message.

Here is my schema

{
    "type": "object",
    "properties": {
        "user_name": { "type": "string" , "minLength": 1},
        "user_email": { "type": "string" , "minLength": 1},
        "user_contact": { "type": "string" , "minLength": 1}
    },
    "required": [ "user_name", 'user_email', 'user_contact']
}

I am using minLength to check that value should contain at least one character. But it also allows empty space.

6

There are 6 answers

0
maria zahid On BEST ANSWER

Right now there is no built in option in AJV to do so.

0
Shivam On

This can now be achieved using ajv-keywords.
Its a collection of custom schemas which can be used for ajv validator.

Changing schema to

{
  "type": "object",
  "properties": {
    "user_name": {
      "type": "string",
      "allOf": [
        {
          "transform": [
            "trim"
          ]
        },
        {
          "minLength": 1
        }
      ]
    },
   // other properties
  }
}

Using ajv-keywords

const ajv = require('ajv');
const ajvKeywords = require('ajv-keywords');
const ajvInstance = new ajv(options);
ajvKeywords(ajvInstance, ['transform']);

The transform keyword specifies what transformations to be executed before validation.

0
Farhad Kazemi On

I did the same thing as Ronconi said yet wanted to emphasis on how you can use the schema, for example "not checking the logic".

ajv.addKeyword({
    keyword: 'isNotEmpty',    
    validate: (schema , data) => {
        if (schema){
            return typeof data === 'string' && data.trim() !== ''
        }
        else return true;
    }
});

const schema = {
    type: "object",
    properties: {
        fname: {
            description: "first name of the user",
            type: "string",
            minLength: 3,
            isNotEmpty: false,
        },
}
0
Lucas Cimon On

Based on @arthur-ronconi answer, here is another solution that works in Typescript, using the latest version of Ajv (documentation):

import Ajv, { _, KeywordCxt } from "ajv/dist/jtd";

const ajv = new Ajv({ removeAdditional: "all", strictRequired: true });
ajv.addKeyword({
  keyword: 'isNotEmpty',
  schemaType: 'boolean',
  type: 'string',
  code(cxt: KeywordCxt) {
    const {data, schema} = cxt;
    if (schema) {
      cxt.fail(_`${data}.trim() === ''`);
    }
  },
  error: {
    message: 'string field must be non-empty'
  }
});
1
Arthur Ronconi On

You can do:

ajv.addKeyword('isNotEmpty', {
  type: 'string',
  validate: function (schema, data) {
    return typeof data === 'string' && data.trim() !== ''
  },
  errors: false
})

And in the json schema:

{
  [...]
  "type": "object",
  "properties": {
    "inputName": {
      "type": "string",
      "format": "url",
      "isNotEmpty": true,
      "errorMessage": {
        "isNotEmpty": "...",
        "format": "..."
      }
    }
  }
}
0
Arthur Ronconi On

I found another way to do this using "not" keyword with "maxLength":

{
  [...]
  "type": "object",
  "properties": {
    "inputName": {
      "type": "string",
      "allOf": [
        {"not": { "maxLength": 0 }, "errorMessage": "..."},
        {"minLength": 6, "errorMessage": "..."},
        {"maxLength": 100, "errorMessage": "..."},
        {"..."}
      ]
    },
  },
  "required": [...]
}

Unfortunately if someone fill the field with spaces it will be valid becouse the space counts as character. That is why I prefer the ajv.addKeyword('isNotEmpty', ...) method, it can uses a trim() function before validate.

Cheers!