GaTechThomas
GaTechThomas

Reputation: 6076

JSON array item validation

I'd like to have tooling to perform certain validations on JSON. Explanation with examples:

Given JSON fragment:

{
    "optionsMinValue": 0
    "optionsMaxValue": 56
    "options": [
        {
            "name": "name1",
            "value": 0
        },
        {
            "name": "name2",
            "value": 1
        },
        {
            "name": "name3",
            "value": 56
        }
  ]
}

Validation examples:

Added bonus validation:

Existing tooling:

Does tooling exist that can be used relatively easily to perform these sorts of checks?

First thought is that something like json-schema validation could be done. It has been a few years since I looked at that as an option, so my hope is that tooling has emerged that is a homerun on this.

Upvotes: 2

Views: 1079

Answers (3)

Ajmal Ahamed
Ajmal Ahamed

Reputation: 152

Joi package is best for these kind of validations

following Joi schema can be used to solve your requirement

Joi.object({
  optionsMinValue: Joi.number().min(0).max(30).required(),

  optionsMaxValue: Joi.number().min(56).max(100).required(),

  options: Joi.array().items(
    Joi.object({
      name: Joi.string().required(),
      value: Joi.number().min(0).max(56).required(),
    })
  ),
});

Following is a sample code that works for your scenario

const inputData = {
  optionsMinValue: 0,
  optionsMaxValue: 56,
  options: [
    {
      name: "name1",
      value: 0,
    },
    {
      name: "name2",
      value: 1,
    },
    {
      name: "name3",
      value: 56,
    },
  ],
};

const Joi = joi; // for node.js use - const Joi = require("joi");

// Schema for validation
const schema = Joi.object({
  optionsMinValue: Joi.number().min(0).max(30).required(),

  optionsMaxValue: Joi.number().min(56).max(100).required(),

  options: Joi.array().items(
    Joi.object({
      name: Joi.string().required(),
      value: Joi.number().min(0).max(56).required(),
    })
  ),
});

const runValidation = (schema, inputData) => {
  const validationResult = Joi.compile(schema)
    .prefs({ errors: { label: "key" }, abortEarly: false })
    .validate(inputData);

  if (validationResult.error) {
    // Validation failed
    console.log("Error, validation failed");
    // Set error message to string
    const errorMessage = validationResult.error.details
      .map((details) => details.message)
      .join(", ");
    console.log("failure reason - ", errorMessage);
    return;
  }
  console.log("validation passed");
};
runValidation(schema, inputData);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/joi-browser.min.js"></script>

Upvotes: 1

Steve
Steve

Reputation: 76

Ajv JSON schema validator - github link

const schema = {
  type: "object",
  properties: {
    name: {type: "string"},
    value: {type: "number", minimum: 0, maximum: 55},
  },
  required: ["name", "value"],
  additionalProperties: false,
}

const option = {
    "name": "name1",
    "value": 0
},

const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/4.4.0/ajv.min.js"></script>

Upvotes: 4

seeker
seeker

Reputation: 864

Even if you use an existing tool, you should write validation rules for that tool. Since you are not an expert in any of these tools, it may be easier to write a few lines of code in your preferred language. For example, in JavaScript it might look like this:

function validateJson(jsonToValidate, maxValue = 56) {
  if (jsonToValidate.optionsMaxValue !== maxValue) {
    console.log("Failure on optionsMaxValue.");
    return false;
  }
  if (jsonToValidate.options.length !== maxValue+1) {
    console.log("Incorrect number of items.");
    return false;
  }
  let values = jsonToValidate.options.map(a => a.value).sort();
  if (values[0] !== 0 || values[maxValue] !== maxValue) {
    console.log("Values out of desired sequence.");
    return false;
  }
  let sum = values.reduce((a, b) => a + b, 0);
  if (sum !== maxValue * (maxValue + 1) / 2) {
    console.log("Values out of desired sequence.");
    return false;
  }
  console.log("Validation PASSED.");
  return true;
}

Let's try with truncated json object:

let jsonSample = {
  "optionsMinValue": 0,
  "optionsMaxValue": 2,
  "options": [{
      "name": "name1",
      "value": 0
    },
    {
      "name": "name2",
      "value": 1
    },
    {
      "name": "name3",
      "value": 2
    }
  ]
};

function validateJson(jsonToValidate, maxValue = 56) {
  if (jsonToValidate.optionsMaxValue !== maxValue) {
    console.log("Failure on optionsMaxValue.");
    return false;
  }
  if (jsonToValidate.options.length !== maxValue+1) {
    console.log("Incorrect number of items.");
    return false;
  }
  let values = jsonToValidate.options.map(a => a.value).sort();
  if (values[0] !== 0 || values[maxValue] !== maxValue) {
    console.log("Values out of desired sequence.");
    return false;
  }
  let sum = values.reduce((a, b) => a + b, 0);
  if (sum !== maxValue * (maxValue + 1) / 2) {
    console.log("Values out of desired sequence.");
    return false;
  }
  console.log("Validation PASSED.");
  return true;
}

validateJson(jsonSample, 2);

Upvotes: 0

Related Questions