JSON処理

JSON処理
```
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) throws Exception {
        // JSON文字列の定義
        String jsonString = "{\n" +
                "\"apiVer1\":\"$$(TEST_NO1)\",\n" +
                "\"apiver2\":\"$$(TEST_NO2 HEAD:11)\",\n" +
                "\"norma\":\"testValue\",\n" +
                "\"apiver\":\"14\",\n" +
                "\"normal2\":\"testValue2\",\n" +
                "\"apiPerson\":{\n" +
                "\"apiVer3\":\"$$(TEST_NO3 HEAD:13)\",\n" +
                "\"kokyaku\":\"$$(kokyakuNo)\",\n" +
                "\"apiVer4\":\"$$(TEST_NO4 HEAD:24)\"\n" +
                "},\n" +
                "\"apiFunds\":{\n" +
                "\"apiVer5\":\"$$(TEST_NO5 HEAD:26)\",\n" +
                "\"apiVer6\":\"$$(TEST_NO6 ERA:yymmdd)\",\n" +
                "\"apiVer7\":\"$$(TEST_NO7 ERA:yymm)\",\n" +
                "\"apiVer8\":\"$$(TEST_NO8 IFNA:3/*)\",\n" +
                "\"apiVer9\":\"$$(TEST_NO9 IFNA:4/*)\",\n" +
                "\"apiVer10\":\"$$(TEST_NO10 IFNA:5/6)\",\n" +
                "\"apiVer11\":\"$$(TEST_NO11 IFNA:7/8)\"\n" +
                "}\n" +
                "}";

        // テストデータのマップを定義
        Map<String, String> bindDateMap = new HashMap<>();
        bindDateMap.put("TEST_NO1", "test1Value");
        bindDateMap.put("TEST_NO2", "123456789012345");
        bindDateMap.put("TEST_NO3", "123456789012345");
        bindDateMap.put("TEST_NO4", "123456789012345678901234567");
        bindDateMap.put("TEST_NO5", "123456789012345678901234567");
        bindDateMap.put("TEST_NO6", "19261224");
        bindDateMap.put("TEST_NO7", "192701");
        bindDateMap.put("TEST_NO8", "");  // 空文字を設定
        bindDateMap.put("TEST_NO9", "");
        bindDateMap.put("TEST_NO10", null);
        bindDateMap.put("TEST_NO11", "200");
        bindDateMap.put("kokyakuNo", "kokyakuNoValue");

        // JSON文字列からキーと対応する値のパターンを抽出
        Map<String, String> extractedKeyPatternMap = extractKeyPatterns(jsonString);
        // 最終的な結果を格納するマップの定義
        Map<String, Object> req = new HashMap<>();

        // 抽出したキーを使って値を加工し、結果マップに格納
        for (Map.Entry<String, String> entry : extractedKeyPatternMap.entrySet()) {
            String jsonKey = entry.getKey();  // JSONのキー
            String patternOrValue = entry.getValue();  // $$()内のパターンまたはそのままの値

            if (patternOrValue.startsWith("$$(")) {
                String pattern = patternOrValue.substring(3, patternOrValue.length() - 1); // $$()を取り除く
                String bindKey = pattern.split(" ")[0];  // パターンからテスト番号を取得
                String value = bindDateMap.get(bindKey);  // テストデータマップから値を取得
                if (value == null || value.isEmpty() || "0".equals(value)) { // 空文字チェックの追加
                    value = "";  // 値がnullまたは"0"の場合には空文字を格納
                }
                String processedValue = processValue(pattern, value);  // 値を加工
                req.put(jsonKey, processedValue);  // 結果をreqマップに追加
            } else {
                req.put(jsonKey, patternOrValue);  // 値をそのままreqマップに追加
            }
        }

        // 結果マップを出力
        for (Map.Entry<String, Object> entry : req.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    // JSON文字列からキーとパターンを抽出するメソッド
    public static Map<String, String> extractKeyPatterns(String jsonString) throws Exception {
        Map<String, String> keyPatternMap = new HashMap<>();
        // JSON文字列をパース
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(jsonString);

        // 再帰的にJSONノードを処理してキーとパターンを抽出
        extractPatternsRecursive(rootNode, "", keyPatternMap);

        return keyPatternMap;
    }

    // 再帰的にJSONノードを処理してキーとパターンを抽出するメソッド
    private static void extractPatternsRecursive(JsonNode node, String parentKey, Map<String, String> keyPatternMap) {
        if (node.isObject()) {
            // JSONオブジェクトの場合、各フィールドを処理
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> field = fields.next();
                String currentKey = parentKey.isEmpty() ? field.getKey() : parentKey + "." + field.getKey();
                extractPatternsRecursive(field.getValue(), currentKey, keyPatternMap);
            }
        } else if (node.isTextual()) {
            // テキストノードの場合、パターンを抽出
            String text = node.asText();
            Pattern pattern = Pattern.compile("\\$\\$\\((.*?)\\)");
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                keyPatternMap.put(parentKey, matcher.group(0));  // $$()のパターンを含めて取得
            } else {
                keyPatternMap.put(parentKey, text);  // パターンが見つからない場合はそのまま取得
            }
        }
    }

    // キーに基づいて値を加工するメソッド
    public static String processValue(String key, String value) throws ParseException {
        if (key.contains("HEAD:")) {
            // HEAD:の場合、指定された文字数だけ切り出す
            int headLength = Integer.parseInt(key.split("HEAD:")[1]);
            if (value.length() <= headLength) {
                return value;  // valueがheadLength以下の場合はそのまま返す
            }
            return value.substring(0, headLength);
        } else if (key.contains("ERA:yymmdd")) {
            // ERA:yymmddの場合、和暦に変換
            return convertToJapaneseEra(value, "yyyyMMdd");
        } else if (key.contains("ERA:yymm")) {
            // ERA:yymmの場合、和暦に変換
            return convertToJapaneseEra(value, "yyyyMM");
        } else if (key.contains("IFNA:") && key.contains("/*")) {
            // IFNA:x/*の場合、値が空またはnullならxに置き換え
            int replacementValue = Integer.parseInt(key.split("IFNA:")[1].split("/")[0]);
            return (value == null || value.isEmpty()) ? String.valueOf(replacementValue) : value;
        } else if (key.contains("IFNA:") && key.split("IFNA:")[1].contains("/")) {
            // IFNA:x/yの場合、値が空またはnullならxに置き換え、値が空でない場合にはyに置き換え
            String[] parts = key.split("IFNA:")[1].split("/");
            int nullValueReplacement = Integer.parseInt(parts[0]);
            int nonNullValueReplacement = Integer.parseInt(parts[1]);
            return (value == null || value.isEmpty()) ? String.valueOf(nullValueReplacement) : String.valueOf(nonNullValueReplacement);
        }

        return value;
    }

    // 西暦を和暦に変換するメソッド
    public static String convertToJapaneseEra(String date, String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date westernDate = sdf.parse(date);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(westernDate);

        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1; // Calendarの月は0から始まるため+1
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        String eraYear;

        if (format.equals("yyyyMMdd")) {
            if (year > 2019 || (year == 2019 && (month > 5 || (month == 5 && day >= 1)))) {
                // 令和 (2019年5月1日から)
                eraYear = String.format("%02d", year - 2018); // 年が1桁の場合に先頭に0を付ける
                return "5" + eraYear + String.format("%02d%02d", month, day);
            } else if (year > 1989 || (year == 1989 && (month > 1 || (month == 1 && day >= 8)))) {
                // 平成 (1989年1月8日から)
                eraYear = String.format("%02d", year - 1988); // 年が1桁の場合に先頭に0を付ける
                return "4" + eraYear + String.format("%02d%02d", month, day);
            } else if (year > 1926 || (year == 1926 && (month > 12 || (month == 12 && day >= 25)))) {
                // 昭和 (1926年12月25日から)
                eraYear = String.format("%02d", year - 1925); // 年が1桁の場合に先頭に0を付ける
                return "3" + eraYear + String.format("%02d%02d", month, day);
            } else if (year > 1912 || (year == 1912 && (month > 7 || (month == 7 && day >= 30)))) {
                // 大正 (1912年7月30日から)
                eraYear = String.format("%02d", year - 1911); // 年が1桁の場合に先頭に0を付ける
                return "2" + eraYear + String.format("%02d%02d", month, day);
            } else if (year > 1868 || (year == 1868 && (month > 1 || (month == 1 && day >= 25)))) {
                // 明治 (1868年1月25日から)
                eraYear = String.format("%02d", year - 1867); // 年が1桁の場合に先頭に0を付ける
                return "1" + eraYear + String.format("%02d%02d", month, day);
            } else {
                // 上記以外の場合、未("0")
                eraYear = "00"; // 年が1桁の場合に先頭に0を付ける
                return "0" + eraYear + String.format("%02d%02d", month, day);
            }
        } else if (format.equals("yyyyMM")) {
            if (year > 2019 || (year == 2019 && month >= 5)) {
                // 令和 (2019年5月から)
                eraYear = String.format("%02d", year - 2018); // 年が1桁の場合に先頭に0を付ける
                return "5" + eraYear + String.format("%02d", month);
            } else if ((year > 1989) || (year == 1989 && month >= 2) || (year == 2019 && month < 5)) {
                // 平成 (1989年2月から2019年4月まで)
                eraYear = String.format("%02d", year - 1988); // 年が1桁の場合に先頭に0を付ける
                return "4" + eraYear + String.format("%02d", month);
            } else if ((year > 1926) || (year == 1927 && month >= 1) || (year == 1989 && month < 2)) {
                // 昭和 (1927年1月から1989年1月まで)
                if (year == 1927 && month == 1) {
                    eraYear = String.format("%02d", year - 1926); // 年が1桁の場合に先頭に0を付ける
                } else {
                    eraYear = String.format("%02d", year - 1926 + 1); // 1927年1月は昭和1年1月とする
                }
                return "3" + eraYear + String.format("%02d", month);
            } else if ((year > 1912) || (year == 1912 && month >= 8) || (year == 1926 && month < 12)) {
                // 大正 (1912年8月から1926年12月まで)
                eraYear = String.format("%02d", year - 1911); // 年が1桁の場合に先頭に0を付ける
                return "2" + eraYear + String.format("%02d", month);
            } else if ((year > 1868) || (year == 1868 && month >= 2) || (year == 1912 && month < 8)) {
                // 明治 (1868年2月から1912年7月まで)
                eraYear = String.format("%02d", year - 1867); // 年が1桁の場合に先頭に0を付ける
                return "1" + eraYear + String.format("%02d", month);
            } else {
                // 上記以外の場合、未("0")
                eraYear = "00"; // 年が1桁の場合に先頭に0を付ける
                return "0" + eraYear + String.format("%02d", month);
            }
        }

        return date;
    }
}

```