bestsource

2개의 json 객체의 차이 가져오기

bestsource 2023. 3. 20. 23:22
반응형

2개의 json 객체의 차이 가져오기

시나리오:2개의 JSON 오브젝트를 비교하여 JSON 오브젝트를 차이 목록과 함께 반환하고 가능하면 커버리지 메트릭 등의 데이터를 더 많이 반환하는 함수를 원합니다.

var madrid = '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}';
var barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}';

compare(madrid, barca)반환되는 오브젝트는 다음과 같습니다.

{"description" : "Bad", "trophies":[{"ucl":"3"}, {"copa":"5"}]}; 

아니면 비슷한 걸 보면 알 수 있을 거예요.

이에 대한 해결책을 아는 사람 있나요?플러그인은 이미 1개 있습니다만, 다른 플러그인이 있는지 알고 싶습니다.

오브젝트 키로 반복하는 재귀 함수를 사용할 수 있습니다.그런 다음 Object.is을 사용하여 테스트합니다.NaN ★★★★★★★★★★★★★★★★★」null 두 , 던지다, 던지다, 던지다, 던지다, 라고 하는 인지 테스트해보세요false0,NaN , 「」null. 를 나열하여 에 있는 하기 위해 obj1그걸 반복하는 거죠

키 값 경우, 이 when when은 、 키 、 음 、 음 、 음 、 음 、 음 음 음 when when 。object2계속 진행됩니다.두 키 값이 모두 오브젝트인 경우 는 재귀적으로 비교할 수 있으며, 이는 재귀적으로 비교됩니다.

function diff(obj1, obj2) {
    const result = {};
    if (Object.is(obj1, obj2)) {
        return undefined;
    }
    if (!obj2 || typeof obj2 !== 'object') {
        return obj2;
    }
    Object.keys(obj1 || {}).concat(Object.keys(obj2 || {})).forEach(key => {
        if(obj2[key] !== obj1[key] && !Object.is(obj1[key], obj2[key])) {
            result[key] = obj2[key];
        }
        if(typeof obj2[key] === 'object' && typeof obj1[key] === 'object') {
            const value = diff(obj1[key], obj2[key]);
            if (value !== undefined) {
                result[key] = value;
            }
        }
    });
    return result;
}

위의 코드는 BSD 라이선스로 어디서든 사용할 수 있습니다.

테스트 링크: https://jsfiddle.net/gartz/vy9zaof2/54/

중요한 관찰 사항으로, 배열을 개체로 변환하고 동일한 인덱스 위치의 값을 비교합니다.이 기능의 대상이 되지 않는 어레이를 비교할 수 있는 방법은 그 밖에도 많이 있습니다.이는 복잡성이 필요하기 때문입니다.

2019년 2월 15일 편집:이 답변은 새로운 ES2017 구문을 추가하고 코멘트에서 사용 사례를 수정하기 위해 변경되었습니다.


이것은 단지 킥오프일 뿐입니다.테스트는 하지 않았지만 필터나 비교기 함수부터 시작했습니다.이것은 재귀적인 것으로, 우선적인 결과를 얻기 위해서 변경해 주세요.

function filter(obj1, obj2) {
    var result = {};
    for(key in obj1) {
        if(obj2[key] != obj1[key]) result[key] = obj2[key];
        if(typeof obj2[key] == 'array' && typeof obj1[key] == 'array') 
            result[key] = arguments.callee(obj1[key], obj2[key]);
        if(typeof obj2[key] == 'object' && typeof obj1[key] == 'object') 
            result[key] = arguments.callee(obj1[key], obj2[key]);
    }
    return result;
}

테스트: http://jsfiddle.net/gartz/Q3BtG/2/

가브리엘 가르츠 버전에 대한 제 변경에 기여하고 있습니다.이것은 완전 모드로 동작하며 어레이 체크를 삭제합니다.항상 false입니다.또한 diff에서 빈 노드를 삭제합니다.

//http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object
var isEmptyObject = function(obj) {
    var name;
    for (name in obj) {
        return false;
    }
    return true;
};

//http://stackoverflow.com/questions/8431651/getting-a-diff-of-two-json-objects
var diff = function(obj1, obj2) {
    var result = {};
    var change;
    for (var key in obj1) {
        if (typeof obj2[key] == 'object' && typeof obj1[key] == 'object') {
            change = diff(obj1[key], obj2[key]);
            if (isEmptyObject(change) === false) {
                result[key] = change;
            }
        }
        else if (obj2[key] != obj1[key]) {
            result[key] = obj2[key];
        }
    }
    return result;
};

rus-diff https://github.com/mirek/node-rus-diff 를 사용하면, MongoDB 호환(fatternal/set) diff 를 작성할 수 있습니다.

// npm install rus-diff
var madrid = {"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]};
var barca = {"type":"team","description":"Bad","trophies":[{"ucl":"3"}]};
var rusDiff = require('rus-diff').rusDiff
console.log(rusDiff(madrid, barca))

출력:

{ '$unset': { 'trophies.1': true },
  '$set': { description: 'Bad', 'trophies.0.ucl': '3' } }

가브리엘 가르츠의 버전을 한 번 더 수정했습니다.각에 대한 나타냅니다.[oldValue, newValue]diff에빈 .

function diffObj( obj1, obj2 ) {

    const result = {};
    if ( Object.is( obj1, obj2 ) ) return undefined;
    if ( ! obj2 || typeof obj2 !== 'object' ) return obj2;
    Object.keys( obj1 || {} ).concat( Object.keys( obj2 || {} ) ).forEach( key => {

        let val;
        if ( obj2[ key ] !== obj1[ key ] && ! Object.is( obj1[ key ], obj2[ key ] ) ) val = [ obj1[ key ], obj2[ key ] ];

        if ( typeof obj2[ key ] === 'object' && typeof obj1[ key ] === 'object' ) {

            const value = diffObj( obj1[ key ], obj2[ key ] );
            if ( value !== undefined ) val = value;

        } else if ( val !== undefined ) {

            result[ key ] = val;

        }

    } );
    return result;

}

는 이 방법이 효과가 있었습니다.

const a ={
    'kk':0,
    'k1':1,
    'k2':2,
    'k4':4, 
    'sub': {
        'xx':0,
        'x1':1,
        'x2':2,
        'x4':4, 
    } 
};
const b ={
    'kk':0,
    'k1':1,
    'k3':3, 
    'k4':44, 
    'sub': {
        'xx':0,
        'x1':1,
        'x3':3, 
        'x4':44, 
    }
};


function ObjectsDiff(o1,o2) {
    const typeObject = function(o){
        return typeof o === 'object';
    };
    const diff = function (o1, o2) {
        const result = {};
        // if first is item is not object
        if (!typeObject(o1) && typeObject(o2)) {
            return o2;
        }
        // if second is item is not object
        else if (typeObject(o1) && !typeObject(o2)) {
            return undefined;
        }
        // if they are equal
        else if (Object.is(o1, o2)) {
            return undefined;
        }
        const keys = Object.keys(o2);
        for (let i=0; i<keys.length; i++) {
            const key = keys[i];
            // if both are objects
            if ( typeObject(o1[key]) && typeObject(o2[key])) {
                // if equal, return nothing
                if ( Object.is(o1[key], o2[key]) ) {
                    // do nothing
                } else if (o1[key] === o2[key]) {
                    // do nothing
                } else {
                    result[key] = diff(o1[key],o2[key]);
                }
            } else if (o1[key] !== o2[key]) {
                result[key] = o2[key];
            } else {
                // do nothing
            }
        }
        return result;
    };
    return [
        diff(o1,o2),
        diff(o2,o1),
    ];
}

console.log( ObjectsDiff(a,b));

다음의 3가지 시나리오가 있습니다.

  1. 두 개체 모두에 속성이 있습니다.

    • 속성 이 두 개체에서 동일한 경우delete두 번째 오브젝트(copy).
  2. 속성이 첫 번째 개체에 있습니다(original두 번째 오브젝트에는 없습니다.이 경우 속성을 두 번째 개체에 추가합니다.

  3. 마지막으로 두 번째 오브젝트에는 속성이 존재하지만 첫 번째 오브젝트에는 존재하지 않습니다.이 경우 아무것도 하지 않습니다.

    function compare(original, copy) {
      for (let [k, v] of Object.entries(original)) {
        if (typeof v === "object" && v !== null) {
          if (!copy.hasOwnProperty(k)) {
            copy[k] = v; // 2
          } else {
            compare(v, copy?.[k]);
          }
        } else {
          if (Object.is(v, copy?.[k])) {
            delete copy?.[k]; // 1
          }
        }
      }
      return JSON.stringify(copy);
    }
    
    const 
      madrid =
        '{"type":"team","description":"Good","trophies":[{"ucl":"10"}, {"copa":"5"}]}',
      barca = '{"type":"team","description":"Bad","trophies":[{"ucl":"3"}]}',
      diff = compare(JSON.parse(madrid), JSON.parse(barca));
    
    console.log(diff);

같은 과제를 안고 라이트 API를 작성했습니다.다른 API는 너무 복잡해서 오브젝트 간에 차이를 만들어 json 데이터로 되돌릴 수 있습니다.필요한 기능을 수행하는 것 같습니다.

diff 개체는 __deleted 또는 __mergeAction과 같은 태그를 사용하여 삭제된 어레이 레코드 또는 어레이 내의 새/업데이트된 레코드 등의 개체에 대한 변경 사항을 추적합니다.그렇지 않으면 변경되는 비개체 키(예의 설명 필드 등)가 델타에 표시됩니다.

// Get the delta between two json objects in a format that can be used by the mergeJson function
var edits = JsonDiffMerge.jsonDiff(originalData, updatedData);

// Merge the edits into the original object. The original object is not modified. The result is returned.
var merged = JsonDiffMerge.mergeJson(true, originalData, edits);

function diff(obj1, obj2) {
    const result = {};
    if (Object.is(obj1, obj2)) {
        return undefined;
    }
    if (!obj2 || typeof obj2 !== 'object') {
        return obj2;
    }
    Object.keys(obj1 || {}).concat(Object.keys(obj2 || {})).forEach(key => {
        if(obj2[key] !== obj1[key] && !Object.is(obj1[key], obj2[key])) {
            result[key] = obj2[key];
        }
        if(typeof obj2[key] === 'object' && typeof obj1[key] === 'object') {
            const value = diff(obj1[key], obj2[key]);
            if (value !== undefined) {
                result[key] = value;
            }
        }
    });
    return result;
}

언급URL : https://stackoverflow.com/questions/8431651/getting-a-diff-of-two-json-objects

반응형