-1

I have the following json schema.

const myJson = {
    "type": "typeName"
    "firstName": "Steven",
    "lastName": "Smith",
    "address": {
        "primary": {
            "city": "abc",
            "street": {
                "name": {
                    "subName": "someName"
                }
            }
        }
    }
}

And I want to loop over each of the properties for required validation on this json, I have the following code so far which works if the property in the json is not nested.

let errors = [];
const typeName = ['firstName', 'lastName'],
const typeAttr = Object.keys(myJson);

typeName.forEach(attr => {
  if (!typeAttr.includes(attr)) {
    errors.push(`Missing field: ${attr}`);
  }
});

How can I add the nested json property like primary, city, street and validate the way I have done it.

user2281858
  • 1,957
  • 10
  • 41
  • 82

3 Answers3

1

I would do something like this. This method gives whether the data is having all the provided keys or not i.e., will return either true or false

let obj = {"type":"typeName","firstName":"Steven","lastName":"Smith","address":{"primary":{"city":"abc","street":{"name":{"subName":"someName"}}}}};

const typeName = ['firstName', 'lastName', 'address', 'address.primary', 'address.primary.city', 'address.primary.street'];

const validate = (data, types) => {
  return types.every(type => {
    // Split the keys using `.`
    const keys = type.split('.');
    // Check if the length is more than 1, 
    // if yes, then we need to check deeply
    if (keys.length > 1) {
      let datum = {
        ...data
      };
      // Check through all the keys found using split 
      for (let key of keys) {
        // if any key is not found or falsy then return false
        if (!datum[key]) {
          return false;
        }
        datum = datum[key];
      }
      return true;
    } else {
      // if the length of the keys is not more than 1 then it means
      // the key is at the top level and return the value as boolean
      return !!data[type]
    }
  })
}

console.log(validate(obj, typeName));

console.log(validate(obj, ['firstName', 'lastName', 'address', 'address.primary', 'address.primary.zip']));

This below method will return the keys that were not present in the provided data

const validate = (data, types) => {
  let errors = [];
  types.forEach(type => {
    const keys = type.split('.');
    let datum = {
      ...data
    };
    // Loop through the keys 
    for (let [index, key] of keys.entries()) {
    // Check if the key is not available in the data
    // then push the corresponding key to the errors array
    // and break the loop
      if (!datum[key]) {
        errors.push(keys.slice(0, index + 1).join('.'));
        break;
      }
      datum = datum[key];
    }
  })
  return errors;
}

const obj = {"type":"typeName","firstName":"Steven","lastName":"Smith","address":{"primary":{"city":"abc","street":{"name":{"subName":"someName"}}}}};

const typeName = ['firstName', 'lastName', 'address', 'address.primary', 'address.primary.city', 'address.primary.street'];
console.log(validate(obj, ['firstName', 'lastName']));
console.log(validate(obj, ['firstName', 'lastName', 'address', 'address.primary', 'address.primary.zip']));
console.log(validate(obj, [...typeName, 'test', 'address.primary.zip', 'address.test.zip']));
Nithish
  • 5,393
  • 2
  • 9
  • 24
1

Here's how you can check nested properties on json object

const myJson = {
  type: "typeName",
  firstName: "Steven",
  lastName: "Smith",
  address: {
    primary: {
      city: "abc",
      street: {
        name: {
          subName: "someName",
        },
      },
    },
  },
};

let errors = [];
const typeName = ["firstName", "lastName", "address.primary", "address.primary.city"];

function checkNested(obj, level, ...rest) {
  if (obj === undefined) return false;
  if (rest.length == 0 && obj.hasOwnProperty(level)) return true;
  return checkNested(obj[level], ...rest);
}

typeName.forEach((attr) => {
  let props = attr.split(".");
  if (!checkNested(myJson, ...props)) {
    errors.push(`Missing field: ${attr}`);
  }
});

console.log(errors);

For reference on how to check Nested properties you can check this answer. Test for existence of nested JavaScript object key

Awais
  • 331
  • 3
  • 11
0

Use JSON Schema, a proposed IETF standard with tons of library implementations available for several languages for describing, generating, and validating JSON documents.

To require your JSON to have all the properties be present, you'll need a JSON Schema like below.

let typeNameSchema = {
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "https://example.com/typename.schema.json",
  "title": "Type Name",
  "description": "A person's name and address details",
  "type": "object",
  "required": [
    "firstName",
    "lastName",
    "address"
  ],
  "properties": {
    "type": {
      "type": "string"
    },
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    },
    "address": {
      "type": "object",
      "required": [
        "primary"
      ],
      "properties": {
        "primary": {
          "type": "object",
          "required": [
            "city",
            "street"
          ],
          "properties": {
            "city": {
              "type": "string"
            },
            "street": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "object",
                  "required": [
                    "subName"
                  ],
                  "properties": {
                    "subName": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Then use any library to validate your JSON data against the above schema. jsonschema is one of the most popular JSON Schema validators for JavaScript. Here's how to validate your myJson data against the above typeNameSchema.

const Validator = require('jsonschema').Validator;
const validator = new Validator();

console.log(validator.validate(myJson, typeNameSchema)); // result

Validation results will be returned in a ValidatorResult object with the most important properties valid of type boolean and errors of type ValidationError[]. ValidationError object will have the property name and error message.

Ravi K Thapliyal
  • 51,095
  • 9
  • 76
  • 89