import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; public class JsonFileCompare { private static Logger log = LoggerFactory.getLogger(JsonFileCompare.class); public static void main(String[] args) { try { ObjectMapper objectMapper = new ObjectMapper(); Path originPath = Paths.get(args[0]); JsonNode twJson = objectMapper.readTree(new String(Files.readAllBytes(originPath))); Set originSet = new HashSet<>(); addKeys("", twJson, originSet, new ArrayList<>()); IntStream.range(1, args.length).forEach(i -> findMissingKeys(Paths.get(args[i]), originSet)); } catch (Exception e) { log.error("{} is not exists or not json files.", args[0], e); System.exit(1); } checkProperties(); } private static void addKeys( String currentPath, JsonNode jsonNode, Set set, List suffix) { if (jsonNode.isObject()) { ObjectNode objectNode = (ObjectNode) jsonNode; Iterator> iter = objectNode.fields(); String pathPrefix = currentPath.isEmpty() ? "" : currentPath + "-"; while (iter.hasNext()) { Map.Entry entry = iter.next(); addKeys(pathPrefix + entry.getKey(), entry.getValue(), set, suffix); } } else if (jsonNode.isValueNode()) { StringBuilder sb = new StringBuilder(currentPath); if (currentPath.contains("-")) { for (Integer suffix1 : suffix) { sb.append("-").append(suffix1); } } set.add(sb.toString()); } } private static void findMissingKeys(Path targetPath, Set originSet) { if (!targetPath.toFile().exists()) return; try { Set targetSet = new HashSet<>(); ObjectMapper objectMapper = new ObjectMapper(); JsonNode json = objectMapper.readTree(new String(Files.readAllBytes(targetPath))); addKeys("", json, targetSet, new ArrayList<>()); Set missingKey = originSet .parallelStream() .filter(key -> !targetSet.contains(key)) .collect(Collectors.toSet()); if (!missingKey.isEmpty()) { log.error( "Missing Key on {} \nMissing Keys: {}", targetPath.getFileName(), missingKey.stream().sorted().collect(Collectors.toList())); System.exit(1); } } catch (Exception e) { log.error("{} is not json files.", targetPath, e); System.exit(1); } } private static void checkProperties() { String path = "./src/main/resources/i18n/"; String extension = ".properties"; Map> map = Arrays.stream( Optional.ofNullable( Paths.get(path).toFile().list((dir, name) -> name.endsWith(extension))) .orElse(new String[0])) .map(s -> s.split(extension)[0]) .collect( Collectors.groupingBy( filename -> filename.split("_")[0], Collectors.mapping(l -> path + l + extension, Collectors.toList()))); for (Map.Entry> entry : map.entrySet()) { List twList = entry .getValue() .stream() .filter(fileName -> fileName.contains("zh_TW")) .collect(Collectors.toList()); List otherList = entry .getValue() .stream() .filter(fileName -> !fileName.contains("zh_TW")) .collect(Collectors.toList()); if (twList.isEmpty() || otherList.isEmpty()) continue; try { Set originKeySet = getKeys(twList.get(0)); for (String target : otherList) { Set targetKeySet = getKeys(target); Set missingSet = originKeySet .parallelStream() .filter(k -> !targetKeySet.contains(k)) .collect(Collectors.toSet()); if (!missingSet.isEmpty()) { log.error( "Missing Key on {} \nMissing Keys: {}", Paths.get(target).getFileName(), missingSet); System.exit(1); } } } catch (Exception e) { log.error("check i18n properties error.", e); System.exit(1); } } } private static Set getKeys(String fileName) throws IOException { Properties properties = new Properties(); properties.load(new FileInputStream(fileName)); return new HashSet(Collections.list(properties.propertyNames())); } }