JsonDiff 적용하기 (변경이력관리)

주야·2024년 4월 16일

지난 주에 이어 사이트 내 변경이력을 어떻게 관리할지 고민 중에
알게된 "JsonDiff"!

말 그대로 Json객체 간 구조 및 내용을 비교하여 달라진 부분을 Json형태로 추출하는 훌륭한 라이브러리이다.

내가 참고한 아래 블로그는 아래와 같다!
<< 탄생님의 JsonDiff vs MapDifference 비교 블로그>>



JsonDiff의 장단점이 적혀져있는데, 기존코드로는 JsonDiff는 "변경 전"값을 확인 할 수 없다고 기재되어 있었다. 이전데이터를 함께 저장하기 위해서 라이브러리를 좀 수정해보려고 한다.

의존성 주입 대신 클래스 하나하나 복붙해서 코드를 넣었다:( 쉽지 않구만...


Member객체 "변경 전" & "변경 후" 데이터를 각각 만들어주고,

1) email 수정
2) role Array 0번째 삭제 => role Array 1번째 내용이 0번째로 당겨짐.
3) role Array 1번째 추가
4) parent.email 수정


결과값

[ {
  "op" : "replace",
  "path" : "/email",
  "value" : "changeTest@email.com"
}, {
  "op" : "remove",
  "path" : "/roles/0",
}, {
  "op" : "add",
  "path" : "/roles/1"
}, {
  "op" : "replace",
  "path" : "/parent/email",
  "value" :"test@email.com"

} ]

라이브러리 수정없이 출력하니,

  • replace(수정) 시 "변경 후 값"만 출력되고, "변경 전 값"은 알 수 없음.
  • 배열에서 remove(삭제) 시 "삭제값" 알 수 없음.
  • add(추가) 시 "추가된 값" 됐는지 알수 없음.


변경 전,후 값을 모두 담는 Json을 받기 위해서는 하기 2개의 클래스 변경이 필요함.

  • DiffFlags.java의 하기 매소드에서 "ADD_ORIGINAL_VALUE_ON_REPLACE" 추가
    public static EnumSet<DiffFlags> dontNormalizeOpIntoMoveAndCopy() {
        return EnumSet.of(OMIT_MOVE_OPERATION, OMIT_COPY_OPERATION, ADD_ORIGINAL_VALUE_ON_REPLACE);
    }
+추가) MOVE & COPY 기능 off, REPLACE 오리지널값을 추가하는 옵션 on

  • JsonDiff.java asJson의 3번째 매개변수를 DiffFlags.default에서 아래로 변경
 public static JsonNode asJson(final JsonNode source, final JsonNode target) {
        return asJson(source, target, DiffFlags.dontNormalizeOpIntoMoveAndCopy());
    }
  • JsonDiff.java getJsonNode의 REPLACE 케이스에 1줄 추가!
  private static ObjectNode getJsonNode(JsonNodeFactory FACTORY, Diff diff, EnumSet<DiffFlags> flags) {
         ............ 생락 ............
        switch (diff.getOperation()) {
           ............ 생락 ............

            case REPLACE:
                jsonNode.put(Constants.PATH, diff.getPath().toString());
                if (flags.contains(DiffFlags.ADD_ORIGINAL_VALUE_ON_REPLACE)) {
                    jsonNode.set(Constants.FROM, diff.getSrcValue()); //추가 "변경전 값"넣기 
                    jsonNode.set(Constants.VALUE, diff.getValue());                }
                break;
			............ 생락 ............
        }

        return jsonNode;
    }

이렇게 설정해주고 다시 돌려주면 아래와 같은 결과값이 나온다.
(참고로 Constants.java에서 key값을 변경했다. value → after, from → before)

결과값

[ {
  "op" : "replace",
  "path" : "/email",
  "after" : "changeTest@email.com",
  "before" : "Test@email.com"
}, {
  "op" : "remove",
  "path" : "/roles/0",
  "before" : {
    "role" : "ROLE_ADMIN"
  }
}, {
  "op" : "add",
  "path" : "/roles/1",
  "after" : {
    "role" : "ROLE_MASTER"
  }
}, {
  "op" : "replace",
  "path" : "/parent/email",
  "after" : "test@email.com",
  "before" : "test2@email.com"
} ]

<<zjsonpatch github 보기>>

profile
개발자

0개의 댓글