2つのJSONの差をラムダで処理する

Google gson の JsonParserを使用して 2つのJSONの差をラムダで処理するもの。

import java.io.Reader;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
/**
 * 2つのJSON比較、key の path 表現は "."区切り、配列は [Index]で表現
 *   例) aaa.bbb[2].c → 30 
 *    {  aaa: { bbb:[ { a:1, b:2, c:3 },{ a:11, b:12, c:13 },{ a:10, b:20, c:30 } ] } }
 */
public final class JSonDiff{
   private BiConsumer<String, Object> leftOnly;
   private BiConsumer<String, Object> rightOnly;
   private BiConsumer<String, Object> same;
   private BiConsumer<String, Object[]> both;
   private Map<String, Object> leftMap;
   private Map<String, Object> rightMap;

   /* 値だけに差がある BiConsumer で キーと値配列指定、[0]=左側JSONの値、[1]=右側JSONの値*/
   public JSonDiff(BiConsumer<String, Object[]> both){
      this.both = both;
   }
   /* 左側JSONしか存在しないBiConsumer で キーと値 */
   public JSonDiff addLeft(BiConsumer<String, Object> leftOnly){
      this.leftOnly = leftOnly;
      return this;
   }
   /* 右側JSONしか存在しないBiConsumer で キーと値 */
   public JSonDiff addRight(BiConsumer<String, Object> rightOnly){
      this.rightOnly = rightOnly;
      return this;
   }
   /* 差がないBiConsumer で キーと値  */
   public JSonDiff addSame(BiConsumer<String, Object> same){
      this.same = same;
      return this;
   }
   /* 差分の検査実行 */
   public void scan(String left, String right){
      scan(new StringReader(left), new StringReader(right));
   }
   public void scan(Reader left, Reader right){
      leftMap = new HashMap<>();
      rightMap = new HashMap<>();
      JsonElement jeLeft = new JsonParser().parse(left);
      if (jeLeft.isJsonObject()){
         jeLeft.getAsJsonObject().entrySet()
         .forEach(entry->leftMap.putAll(maped(entry.getKey(), entry.getValue(), leftMap)));
      }
      JsonElement jeRight = new JsonParser().parse(right);
      if (jeRight.isJsonObject()){
         jeRight.getAsJsonObject().entrySet()
         .forEach(entry->rightMap.putAll(maped(entry.getKey(), entry.getValue(), rightMap)));
      }
      leftMap.entrySet().forEach(le->{
         if (rightMap.containsKey(le.getKey())){
            Object l = le.getValue();
            Object r = rightMap.get(le.getKey());
            if (l==null){
               if (r==null){
                  if (same != null) same.accept(le.getKey(), null);
               }else{
                  both.accept(le.getKey(), new Object[]{ l, r });
               }
            }else{
               if (r==null){
                  both.accept(le.getKey(), new Object[]{ l, r });
               }else{
                  if (l.equals(r)){
                     if (same != null) same.accept(le.getKey(), l);
                  }else{
                     both.accept(le.getKey(), new Object[]{ l, r });
                  }
               }
            }
         }else{
            if (leftOnly != null) leftOnly.accept(le.getKey(), le.getValue());
         }
      });
      rightMap.entrySet().forEach(re->{
         if (!leftMap.containsKey(re.getKey())){
            if (rightOnly != null) rightOnly.accept(re.getKey(), re.getValue());
         }
      });
   }
   private Map<String, Object> maped(String key, JsonElement je, Map<String, Object> map){
      if (je.isJsonNull()){
         map.put(key, null);
      }else if(je.isJsonObject()){
         je.getAsJsonObject().entrySet()
         .forEach(entry->map.putAll(maped(key + "." + entry.getKey(), entry.getValue(), map)));
      }else if(je.isJsonArray()){
         JsonArray jary = je.getAsJsonArray();
         int i = 0;
         for(JsonElement e:jary){
            maped(key + "[" + i + "]", e, map);
            i++;
         }
      }else if(je.isJsonPrimitive()){
         JsonPrimitive p = je.getAsJsonPrimitive();
         if (p.isNumber()){
            map.put(key, p.getAsDouble());
         }else if(p.isString()){
            map.put(key, p.getAsString());
         }else if(p.isBoolean()){
            map.put(key, p.getAsBoolean());
         }else if(p.isJsonNull()){
            map.put(key, null);
         }
      }
      return map;
   }
}

使用例

try(Reader leftReader = new FileReader(new File("sample1.json"));
    Reader rightReader = new FileReader(new File("sample2.json"))){

   JSonDiff diff = new JSonDiff((k, ary)->{
      // 同一キー、差分、k = key , ary[0]:sample1.json の値、ary[1]:sample2.json の値
   });
   diff.addLeft((k, v)->{
      // sample1.json だけに存在、k = key , v = 値
   });
   diff.addRight((k, v)->{
      // sample2.json だけに存在、k = key , v = 値
   });
   diff.addSame((k, v)->{
      // 両方同じキーと値である、k = key , v = 値
   });
   diff.scan(leftReader, rightReader);

}catch(Exception e){
   e.printStackTrace();
}