Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

73
LINES

< > BotCompany Repo | #1026301 - JsonDiff

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (2818L/18K).

sclass JsonDiff {
  srecord DiffResult(O a, O b) {}
  
  // key made from getListKey
  srecord GatheredKey(S key, O value) {
    O get() { ret value; }
  }

  sclass Removed > DiffResult { *(O *a, O *b) {} } // b missing
  sclass Added > DiffResult { *(O *a, O *b) {} } // a missing
  sclass DifferentType > DiffResult { *(O *a, O *b) {} }
  sclass Different > DiffResult { *(O *a, O *b) {} } // same type, generally different

  // paths are usually L<String>, but IDs gathered by getListKey can also be in there
  
  IF1<L, S> getListKey; // key field for diffing lists. argument is path
  
  // returns null if identical
  O diff(S json1, S json2) {
    O o1 = jsonDecode(json1), o2 = jsonDecode(json2);
    ret diff(json1, json2, new L);
  }
  
  // a, b = decoded JSON
  O diff(O a, O b) {
    ret diff(a, b, new L);
  }
  
  // a, b = decoded JSON
  O diff(O a, O b, L path) {
    if (eq(a, b)) null;
    if (a == null) ret new Added(a, b);
    if (b == null) ret new Removed(a, b);
    if (a.getClass() != b.getClass()) ret new DifferentType(a, b);
    // from here on, we know that a and b have the same type
    if (a cast Map)
      ret diffMaps(a, (Map) b, path);
     
    if (a cast L)
      try object diffLists(a, (L) b, path);
      
    ret new Different(a, b);
  }
  
  O diffMaps(Map a, Map b, L path) {
    ret withoutNullValues
    (mapKeyAndFunction_lhm(concatAsOrderedSet(keys(a), keys(b)),
      key -> {
        temp tempAddToList(path, key);
        ret diff(a.get(key), b/Map.get(key), path);
      }));
  }
  
  O diffLists(L a, L b, L path) {
    S key = callF(getListKey, path);
    if (key == null) null;
    Map mapA = gatherListElements(a, key, path);
    if (mapA == null) null;
    Map mapB = gatherListElements(b, key, path);
    if (mapB == null) null;
    ret diffMaps(mapA, mapB, path);
  }
  
  Map gatherListElements(L l, S key, L path) {
    new LinkedHashMap mapOut;
    for (O x : l) {
      if (!x instanceof Map)
        ret null with print("Can't get object key " + key + " of non-map (path: " + path + ")");
      mapOut.put(new GatheredKey(key, x/Map.get(key)), x);
    }
    ret mapOut;
  }
}

download  show line numbers  debug dex   

Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pzhvpgtvlbxg, tvejysmllsmz

No comments. add comment

Snippet ID: #1026301
Snippet name: JsonDiff
Eternal ID of this version: #1026301/24
Text MD5: 080d4f10b8b5a7c6ffad2a6c17ae4387
Transpilation MD5: d87170cd9534f76ee00b78ef35ecf234
Author: stefan
Category: javax / discord
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-12-15 21:34:31
Source code size: 2214 bytes / 73 lines
Pitched / IR pitched: No / No
Views / Downloads: 104 / 466
Version history: 23 change(s)
Referenced in: [show references]

Formerly at http://tinybrain.de/1026301 & http://1026301.tinybrain.de