0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaのJacksonライブラリを使い、再帰的にJSONのキーを変換

Last updated at Posted at 2025-03-23

Java 17

  • ObjectMapper を使用してJSONを Map に変換
  • Map のキーを keyMap に基づいて変更
  • ネストされた Map は再帰処理で変換
  • List 内に Map があれば再帰処理
  • LinkedHashMap は挿入した順序を保持するために使用

方法1. 変換表のMapを宣言&設定(プログラム内でput)

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.*;

public class JsonKeyConverter {
    public static void main(String[] args) throws Exception {
        String jsonStr = """
        {
          "name": "taro",
          "age": 23,
          "sex": "man",
          "hobby": {
            "outdoor": {
              "land": ["running", "walking"],
              "sea": ["swimming", "fishing"]
            },
            "indoor": ["movie", "game", "card"]
          }
        }
        """;

        // 旧 → 新のキーの変換マップ
        Map<String, String> keyMap = new HashMap<>();
        keyMap.put("name", "full_name");
        keyMap.put("age", "years_old");
        keyMap.put("sex", "gender");
        keyMap.put("hobby", "interests");
        keyMap.put("outdoor", "outside_activities");
        keyMap.put("indoor", "inside_activities");
        keyMap.put("land", "on_land");
        keyMap.put("sea", "in_sea");

        // JSONをマップに変換
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> jsonMap = null;
		try {
			jsonMap = objectMapper.readValue(jsonStr, new TypeReference<>() {});
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        // キーを変換
        Map<String, Object> convertedMap = convertKeys(jsonMap, keyMap);

        // JSONに戻す
        String newJsonStr = null;
		try {
			newJsonStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(convertedMap);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        System.out.println(newJsonStr);
    }

    // 再帰的にキーを変換
    private static Map<String, Object> convertKeys(Map<String, Object> original, Map<String, String> keyMap) {
        Map<String, Object> converted = new LinkedHashMap<>();
        for (Map.Entry<String, Object> entry : original.entrySet()) {
            String newKey = keyMap.getOrDefault(entry.getKey(), entry.getKey()); // 変換マップにある場合は新キーを使用
            Object value = entry.getValue();

            if (value instanceof Map) {
                value = convertKeys((Map<String, Object>) value, keyMap); // 再帰処理
            } else if (value instanceof List) {
                value = convertList((List<Object>) value, keyMap);
            }

            converted.put(newKey, value);
        }
        return converted;
    }

    // List内のMapも再帰的に処理
    private static List<Object> convertList(List<Object> list, Map<String, String> keyMap) {
        List<Object> convertedList = new ArrayList<>();
        for (Object item : list) {
            if (item instanceof Map) {
                convertedList.add(convertKeys((Map<String, Object>) item, keyMap));
            } else {
                convertedList.add(item);
            }
        }
        return convertedList;
    }
}

実行

{
  "full_name" : "taro",
  "years_old" : 23,
  "gender" : "man",
  "interests" : {
    "outside_activities" : {
      "on_land" : [ "running", "walking" ],
      "in_sea" : [ "swimming", "fishing" ]
    },
    "inside_activities" : [ "movie", "game", "card" ]
  }
}

方法2. 変換表のMapを宣言&設定(プロパティファイルから読み込み)

src/main/resources/key_mapping.properties
name=full_name
age=years_old
sex=gender
hobby=interests
outdoor=outside_activities
indoor=inside_activities
land=on_land
sea=in_sea
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.*;

public class JsonKeyConverter {
    public static void main(String[] args) throws Exception {
        String jsonStr = """
        {
          "name": "taro",
          "age": 23,
          "sex": "man",
          "hobby": {
            "outdoor": {
              "land": ["running", "walking"],
              "sea": ["swimming", "fishing"]
            },
            "indoor": ["movie", "game", "card"]
          }
        }
        """;

        // 旧 → 新のキーの変換マップ
        Map<String, String> keyMap = loadKeyMappings("key_mapping");

        // JSONをマップに変換
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> jsonMap = null;
		try {
			jsonMap = objectMapper.readValue(jsonStr, new TypeReference<>() {});
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        // キーを変換
        Map<String, Object> convertedMap = convertKeys(jsonMap, keyMap);

        // JSONに戻す
        String newJsonStr = null;
		try {
			newJsonStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(convertedMap);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        System.out.println(newJsonStr);
    }

    // 再帰的にキーを変換
    private static Map<String, Object> convertKeys(Map<String, Object> original, Map<String, String> keyMap) {
        Map<String, Object> converted = new LinkedHashMap<>();
        for (Map.Entry<String, Object> entry : original.entrySet()) {
            String newKey = keyMap.getOrDefault(entry.getKey(), entry.getKey()); // 変換マップにある場合は新キーを使用
            Object value = entry.getValue();

            if (value instanceof Map) {
                value = convertKeys((Map<String, Object>) value, keyMap); // 再帰処理
            } else if (value instanceof List) {
                value = convertList((List<Object>) value, keyMap);
            }

            converted.put(newKey, value);
        }
        return converted;
    }

    // List内のMapも再帰的に処理
    private static List<Object> convertList(List<Object> list, Map<String, String> keyMap) {
        List<Object> convertedList = new ArrayList<>();
        for (Object item : list) {
            if (item instanceof Map) {
                convertedList.add(convertKeys((Map<String, Object>) item, keyMap));
            } else {
                convertedList.add(item);
            }
        }
        return convertedList;
    }
    
    private static Map<String, String> loadKeyMappings(String baseName) {
        Map<String, String> keyMap = new HashMap<>();
    
        try {
            ResourceBundle bundle = ResourceBundle.getBundle(baseName);
            for (String key : bundle.keySet()) {
                String value = bundle.getString(key);
                
                if (StringUtils.isEmpty(value)) {
                    throw new IllegalArgumentException("エラー: キー '" + key + "' の値が空です。プロパティファイルを修正してください。");
                }
    
                keyMap.put(key, value);
            }
        } catch (MissingResourceException e) {
            System.err.println("エラー: プロパティファイル '" + baseName + ".properties' が見つかりません。");
            throw e; // そのまま例外を投げて処理を中断
        }
    
        return keyMap;
    }
}

実行

{
  "full_name" : "taro",
  "years_old" : 23,
  "gender" : "man",
  "interests" : {
    "outside_activities" : {
      "on_land" : [ "running", "walking" ],
      "in_sea" : [ "swimming", "fishing" ]
    },
    "inside_activities" : [ "movie", "game", "card" ]
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?