'JSON schema check on number of attributes in an object within an array

I'm using AJV JSON schema validator

Trying to validate that objects held in an array have exactly one attribute/ field, using this constraint.

I used this base schema:

{
  "$id": "ObjectProps.json",
  "type": "object",
  "title": "test thing",
  "description": "test thing",
  "properties": {
    "upn": {
      "$id": "#/properties/upn",
      "type": "string",
      "title": "upn as email format.",
      "description": "upn",
      "minLength": 1,
      "maxLength": 255,
      "examples": [
        "[email protected]"
      ]
    },

    "actions": {
      "$id": "#/properties/actions",
      "type": "object",
      "title": "The actions",
      "description": "Actions to display",
      "default": {},
      "examples": [{
        "actions": {
          "content": [{
              "Google": "aHR0cDovL3d3dy5nb29nbGUuY29t"
            },
            {
              "Amazon": "aHR0cHM6Ly93d3cuYW1hem9uLmNvbQ=="
            }
          ]
        }
      }],
      "properties": {
        "content": {
          "$id": "#/properties/content",
          "type": "array",
          "title": "The content",
          "description": "Content items ",
          "default": [],
          "items": [{
            "$id": "#/properties/content/item",
            "type": "object",
            "title": "The content item",
            "description": "Key value pairs",
            "maxProperties": 1,
            "minProperties": 1,
            "additionalProperties": {
              "type": "string"
            },
            "examples": [
              "{ \"Google\": \"aHR0cDovL3d3dy5nb29nbGUuY29t\" }"
            ]
          }]
        }
      }
    }
  },
  "additionalProperties": false

}

.. using this code:

    const Ajv = require("ajv").default 
    const addFormats = require('ajv-formats').default; 
    const ajv = new Ajv( { strict: false, allErrors: true, strictTuples: false, useDefaults: true } ); 
    const testSchema = require("./ObjectProps.json");

    const schemaValidationFunction = ajv.compile(testSchema);

    console.log("Loaded!");

    const test_json2 = require('./testObject.json');

    function checkSchema(message) {

    let valid = schemaValidationFunction(message);
    let validationErrors;

    if (!valid) {
        validationErrors = schemaValidationFunction.errors.map(function (error) {
            return { path: error.allErrors, message: error.message };

        });
    }

    return [valid, validationErrors];

    }

    console.log("Checking: "+JSON.stringify(test_json2));

    let [valid, errors] =  checkSchema(test_json2);

    if (!valid) { 
        console.log(Message failed schema validation errors=${ JSON.stringify(errors) }); 
    } else { 
        console.log("Message was valid!"); 
    }

RESULTS

(1) The above (with empty object as first element of array) as follows..

    {
      "upn": "[email protected]",
      "actions": {
        "content": [
          {

          },
          {
            "wibble": "aHR0cHM6Ly9kZWp1YW4ubmV0",
            "Station2": "aHR0cHM6Ly9kZWp1YW4ubmV0"
          },
          {
            "navigate": "aHR0cDovL3JvZG9sZm8ub3Jn"
          },
          {
            "plop": "aHR0cHM6Ly9kZWp1YW4ubmV0"
          },
          {
            "Cambridgeshire": "aHR0cDovL2pveS5jb20="
          }
        ]
      }
    }

.. reports the following error correctly: "Message failed schema validation errors=[{"message":"must NOT have fewer than 1 items"}] " , but it doesn't mention the second object, invalid with 2 fields.

(2) With more than one field/ attribute in the first object of the array:

    {
      "upn": "[email protected]",
      "actions": {
        "content": [
          {
            "wibble": "aHR0cHM6Ly9kZWp1YW4ubmV0",
            "Station2": "aHR0cHM6Ly9kZWp1YW4ubmV0"
          },
          {

          },
          {
            "navigate": "aHR0cDovL3JvZG9sZm8ub3Jn"
          },
          {
            "plop": "aHR0cHM6Ly9kZWp1YW4ubmV0"
          },
          {
            "Cambridgeshire": "aHR0cDovL2pveS5jb20="
          }
        ]
      }
    }

.. I get the following correct message: "Message failed schema validation errors=[{"message":"must NOT have more than 1 items"}]", but it doesn't mention the second invalid object (in previous example was the first object) with too few fields.

(3) And most worrying, if the first object in the array is valid, and anything else invalid, e.g. 2nd and 3rd objects are invalid here :

    {
      "upn": "[email protected]",
      "actions": {
        "content": [
          {
            "plop": "aHR0cHM6Ly9kZWp1YW4ubmV0"
          },
          {

          },
          {
            "wibble": "aHR0cHM6Ly9kZWp1YW4ubmV0",
            "Station2": "aHR0cHM6Ly9kZWp1YW4ubmV0"
          },
          {
            "navigate": "aHR0cDovL3JvZG9sZm8ub3Jn"
          },
          {
            "Cambridgeshire": "aHR0cDovL2pveS5jb20="
          }
        ],
        "styledAsLinks": true
      }
    }

.. gives the result: "Message was valid!", which appears to confirm that ajv doesn't seem to check anything after the first object in an array.


SUMMARY

Ajv does not appear to properly validate object field count using 'maxProperties' or 'minProperties' for objects held within an array at array index > 0, if the array has more than one element and the first element is valid and some subsequent elements are not valid.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source