比较两个JSON对象,如果键和值使用Javascript匹配,则返回true

时间:2019-04-25 15:44:49

标签: javascript

我有两个JSON对象,如果键和值匹配,则想返回'true'值。 d1和d2的所有三个值都应匹配。

var d1 = [{"deviceid":"867874031097770","simno":"232ff33","slot":"1"},{"deviceid":"86787403100","simno":"ss343433","slot":"2"}];

var d2 = {"deviceid":"867874031097770","simno":"232ff33","slot":"1"};

我尝试使用以下代码,但不适用于JSON值数组。

function equals ( x, y ) {
    // If both x and y are null or undefined and exactly the same
    if ( x === y ) {
        return true;
    }

    // If they are not strictly equal, they both need to be Objects
    if ( ! ( x instanceof Object ) || ! ( y instanceof Object ) ) {
        return false;
    }

    // They must have the exact same prototype chain, the closest we can do is
    // test the constructor.
    if ( x.constructor !== y.constructor ) {
        return false;
    }

    for ( var p in x ) {
        // Inherited properties were tested using x.constructor === y.constructor
        if ( x.hasOwnProperty( p ) ) {
            // Allows comparing x[ p ] and y[ p ] when set to undefined
            if ( ! y.hasOwnProperty( p ) ) {
                return false;
            }

            // If they have the same strict value or identity then they are equal
            if ( x[ p ] === y[ p ] ) {
                continue;
            }

            // Numbers, Strings, Functions, Booleans must be strictly equal
            if ( typeof( x[ p ] ) !== "object" ) {
                return false;
            }

            // Objects and Arrays must be tested recursively
            if ( !equals( x[ p ],  y[ p ] ) ) {
                return false;
            }
        }
    }

    for ( p in y ) {
        // allows x[ p ] to be set to undefined
        if ( y.hasOwnProperty( p ) && ! x.hasOwnProperty( p ) ) {
            return false;
        }
    }
    return true;
}

4 个答案:

答案 0 :(得分:2)

您可以获取所有键并检查两个对象及其值的存在。

如果数组中的一个对象与给定对象匹配,则可以使用Array#some

function compare(a, b) {
    return [...new Set([...Object.keys(a), ...Object.keys(b)])]
        .every(k => k in a && k in b && a[k] === b[k]);
}

var d1 = [{ deviceid: "867874031097770", simno: "232ff33", slot: "1" },{ deviceid: "86787403100", simno: "ss343433", slot: "2" }],
    d2 = { deviceid: "867874031097770", simno: "232ff33", slot: "1" },
    result = d1.map(compare.bind(null, d2)),
    isMatching = d1.some(compare.bind(null, d2));

console.log(isMatching);
console.log(result);

答案 1 :(得分:0)

  

它们必须具有完全相同的原型链,我们能做的最接近的是   测试构造函数。

实际上,您可以测试原型:

if (Object.getPrototypeOf(x) !== Object.getPrototypeOf(y)) {
    return false;
}

听起来像您想要的

  1. 成为对象:typeof x === "object"是检查的最佳方式
  2. 它们具有相同的原型链:请参见上文
  3. 要具有完全相同的属性:您可以将for-in用于所有可枚举属性,或将getOwnPropertyNames用于所有以字符串命名的属性(包括不可枚举),或将getOwnPropertySymbols用作所有以符号命名的属性(包括不可枚举),或者以字符串命名和以符号命名的属性都为Reflect.ownKeys
  4. 比较浅

如果是这样,应该遵循以下几点:

function equals(x, y) {
    // If both x and y are null or undefined and exactly the same
    if (x === y) {
        return true;
    }

    // If they are not strictly equal, they both need to be Objects
    if (typeof x !== "object" || typeof y !== "object") {
        return false;
    }

    // Can't compare `null` with non-`null`
    if (!x || !y) { // This works because we did the `x === y` check earlier)
        return false;
    }

    // They must have the exact same prototype chain
    if (Object.getPrototypeOf(x) !== Object.getPrototypeOf(y)) {
        return false;
    }

    // Compare own properties (including non-enumerable ones)
    const xkeys = Reflect.ownKeys(x);
    const ykeys = Reflect.ownKeys(y);
    if (xkeys.length !== ykeys.length) {
        return false;
    }
    for (const key of xkeys) {
        if (!ykeys.includes(key) || x[key] !== y[key]) {
            return false;
        }
    }

    return true;
}

实时示例:

function equals(x, y) {
    // If both x and y are null or undefined and exactly the same
    if (x === y) {
        return true;
    }

    // If they are not strictly equal, they both need to be Objects
    if (typeof x !== "object" || typeof y !== "object") {
        return false;
    }

    // Can't compare `null` with non-`null`
    if (!x || !y) { // This works because we did the `x === y` check earlier)
        return false;
    }

    // They must have the exact same prototype chain
    if (Object.getPrototypeOf(x) !== Object.getPrototypeOf(y)) {
        return false;
    }

    // Compare own properties (including non-enumerable ones)
    const xkeys = Reflect.ownKeys(x);
    const ykeys = Reflect.ownKeys(y);
    if (xkeys.length !== ykeys.length) {
        return false;
    }
    for (const key of xkeys) {
        if (!ykeys.includes(key) || x[key] !== y[key]) {
            return false;
        }
    }

    return true;
}

const d1 = [{ deviceid: "867874031097770", simno: "232ff33", slot: "1" },{ deviceid: "86787403100", simno: "ss343433", slot: "2" }];
const d2 = { deviceid: "867874031097770", simno: "232ff33", slot: "1" };

for (const [index, entry] of d1.entries()) {
    console.log(`${index}: ${equals(entry, d2)}`);
}

但是,

检查继承的属性。如果您想这样做,您可能会具有这样的帮助程序功能来获取所有属性:

function getAllPropertyKeys(obj) {
    const result = new Set();
    while (obj && obj !== Object.prototype) {
        for (const key of Reflect.ownKeys(obj)) {
            result.add(key);
        }
        obj = Object.getPrototypeOf(obj);
    }
    return [...result];
}

...然后用它代替Reflect.ownKeys

实时示例:

function getAllPropertyKeys(obj) {
    const result = new Set();
    while (obj && obj !== Object.prototype) {
        for (const key of Reflect.ownKeys(obj)) {
            result.add(key);
        }
        obj = Object.getPrototypeOf(obj);
    }
    return [...result];
}

function equals(x, y) {
    // If both x and y are null or undefined and exactly the same
    if (x === y) {
        return true;
    }

    // If they are not strictly equal, they both need to be Objects
    if (typeof x !== "object" || typeof y !== "object") {
        return false;
    }

    // Can't compare `null` with non-`null`
    if (!x || !y) { // This works because we did the `x === y` check earlier)
        return false;
    }

    // They must have the exact same prototype chain
    if (Object.getPrototypeOf(x) !== Object.getPrototypeOf(y)) {
        return false;
    }

    // Compare own properties (including non-enumerable ones)
    const xkeys = getAllPropertyKeys(x);
    const ykeys = getAllPropertyKeys(y);
    if (xkeys.length !== ykeys.length) {
        return false;
    }
    for (const key of xkeys) {
        if (!ykeys.includes(key) || x[key] !== y[key]) {
            return false;
        }
    }

    return true;
}

const d1 = [{ deviceid: "867874031097770", simno: "232ff33", slot: "1" },{ deviceid: "86787403100", simno: "ss343433", slot: "2" }];
const d2 = { deviceid: "867874031097770", simno: "232ff33", slot: "1" };

for (const [index, entry] of d1.entries()) {
    console.log(`${index}: ${equals(entry, d2)}`);
}

答案 2 :(得分:0)

您可以对d2进行分类,并与d1中的每个条目进行比较。只要在JSON.stringify中提供替换函数作为第二个参数,即可确保在对对象进行字符串化时保持顺序。

  

不保证非数组对象的属性以任何特定顺序进行字符串化。不要依赖于字符串化中同一对象内属性的顺序。

function replacer(obj) {
  return Object.keys(obj).sort();
}

var d1 = [{"deviceid":"867874031097770", "simno":"ss343433", "slot":"1"}, 
          {"deviceid":"867874031097770","simno":"ss343433","slot":"1"}];

var d2 = {"deviceid":"867874031097770","slot":"1", "simno":"ss343433"};

function equals(searchArr, objToCheck) {
  var allEqual = true;
  for (index in searchArr) {
    const item = searchArr[index];
    if (JSON.stringify(item, replacer(item)) !== JSON.stringify(objToCheck, replacer(objToCheck))) {
      (objToCheck)));
      allEqual = false;
      break;
    }
  }
  return allEqual;
}

if (equals(d1, d2)) {
  console.log('All values of properties of d2 match with all entries in d1')
} else {
  console.log('d2 values do not match with all entries in d1');
}

答案 3 :(得分:-1)

您可以字符串化并只比较两个json。

JSON.stringify(d1) == JSON.stringify(d2)