0

I receive a JSON object through an HTTP request.I just want to check if that object has only the fields that I want, don't need to check their value. I did this:

function checkObject(o1, o2) {
  for (const p1 in o1) {
     for (const p2 in o2) {
      if (o1.hasOwnProperty(p2) === false) {
        return false;
      }
      if (o2.hasOwnProperty(p1) === false) {
        return false;
      }
    }
   }
  return true;
}

This is the valid object. I want to accept only requests with this body, don't care about the values.

const validObject = {
  country: '',
  name: '',
  zip: '',
  //etc
};

after this i do an if statement like:

if(checkObject(validObject, receivedObject)){
    //do stuff here
}else{
    //reject the request
}

Ok this works, but it is too ugly. It does not pass the lint test and there are too many for loops. What do you think? is there an alternative to do the same thing? Thank you!!

  • First get the keys: `const keys1 = Object.keys(o1)`. Next, sort them alphabetically: `keys1.sort((a, b) => a > b)`. Finally, stringify: `const json1 = JSON.stringify(keys1);`. The resulting two strings should be identical. –  Nov 26 '20 at 21:49
  • Also, depending on the library you are using to write your http endpoints, it may be possible that it already includes a way to validate the content you receive. Chris G's idea will work pretty good. – germanio Nov 26 '20 at 21:51
  • Duplicate: [How can I check that two objects have the same set of property names?](https://stackoverflow.com/questions/14368596/how-can-i-check-that-two-objects-have-the-same-set-of-property-names) cc @GuerricP –  Nov 26 '20 at 21:59
  • Thak you guys! @ChrisG yeah that works. –  Nov 27 '20 at 08:36

2 Answers2

2

If you're interested there is a spec for JSON schema validation, and there are implementations for JavaScript like ajv.

Now I think this would be too much for what you need. The implementation of checkObject could be:

const valid = {
  foo: '',
  bar: ''
}

const okay = {
  bar: '',
  foo: ''
}

const notEnough = {
  foo: ''
}

const tooMuch = {
  foo: '',
  bar: '',
  foobar : ''
}

function checkObject(validObject, receivedObject) {
  const validKeys = Object.keys(validObject);
  const receivedKeys = Object.keys(receivedObject);
  return validKeys.length === receivedKeys.length
    && validKeys.every(value => ~receivedKeys.indexOf(value));
}

console.log(checkObject(valid, okay));
console.log(checkObject(valid, notEnough));
console.log(checkObject(valid, tooMuch));
Guerric P
  • 30,447
  • 6
  • 48
  • 86
  • Doesn't work if the objects' keys are in different order, eg `const okay = {bar: '', foo: ''}` – James Nov 26 '20 at 22:49
  • 1
    @James thanks for pointing out, I've fixed that – Guerric P Nov 26 '20 at 22:52
  • Curious what is the `~receivedKeys` tilde doing in this case @GuerricP – konsalex Aug 31 '23 at 09:07
  • @konsalex it's just a JavaScript hack which consists in using the [bitwise not operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_NOT) in order to return `0` (which is falsy) when the input is `-1`. It returns truthy values (numbers different than `0`) in other cases – Guerric P Aug 31 '23 at 19:27
0

here is a lodash version


import _ from "lodash"


function checkObject(o1,o2){
  return !_(o1).keys().intersection(_.keys(o2)).isEmpty();
}

Mars
  • 873
  • 1
  • 11
  • 24