- スネークケース変換は「Java の名前を“DB や設定ファイルの世界”に合わせる」技
- まず「スネークケースって何?」をざっくり整理する
- 基本方針:「大文字の“境目”で区切って、つなぎ直す」
- 実装ステップ1:キャメルケースを snake_case に変換する
- 実装ステップ2:SCREAMING_SNAKE_CASE に変換する
- 例題:Java フィールド名から DB カラム名を作る
- 例題:フィールド名から環境変数名(SCREAMING_SNAKE_CASE)を作る
- 例題:JSON のキー名を snake_case にそろえる
- エッジケースと設計のポイント
- まとめ:スネークケース変換ユーティリティで身につけたい感覚
スネークケース変換は「Java の名前を“DB や設定ファイルの世界”に合わせる」技
キャメルケース変換が「外の世界を Java っぽくする」技だとしたら、
スネークケース変換はその逆で、「Java の名前を DB や設定ファイルの世界に合わせる」技です。
userName → user_nameUserName → user_namecreatedAt → created_at
こんな変換ができると、次のような場面でとても楽になります。
- Java のフィールド名から DB カラム名を自動生成したい
- DTO のプロパティ名から JSON のキー名(
user_name)を作りたい - 設定クラスのフィールド名から、環境変数名(
USER_NAME)を作りたい
ここでは、「キャメルケース → スネークケース」を軸に、実務で使えるユーティリティを組み立てていきます。
まず「スネークケースって何?」をざっくり整理する
snake_case と SCREAMING_SNAKE_CASE
スネークケース(snake_case)は、単語をアンダースコア _ でつなぐ書き方です。
user_namecreated_atorder_item_id
さらに、全部大文字にした USER_NAME のような形は、
「SCREAMING_SNAKE_CASE(スクリーミングスネークケース)」と呼ばれ、
環境変数名や定数名でよく使われます。
今回のユーティリティでは、
- camelCase / PascalCase → snake_case
- camelCase / PascalCase → SCREAMING_SNAKE_CASE
の両方を作れるようにしておくと、業務でかなり使い回せます。
基本方針:「大文字の“境目”で区切って、つなぎ直す」
いきなり置換しないで「境目を見つける」ことから始める
キャメルケース → スネークケース変換の本質は、
「大文字が出てきたところを“単語の境目”とみなして、アンダースコアを挟む」ことです。
userNameu ser N ame とバラすのではなく、user と Name に分けたい。
createdAtcreated と At に分けたい。
つまり、「小文字+大文字」の境目を見つけて、そこに _ を入れるイメージです。
これを正規表現で表現すると、かなりスッキリ書けます。
実装ステップ1:キャメルケースを snake_case に変換する
正規表現で「小文字と大文字の境目」にアンダースコアを挟む
まずは、userName → user_name のような基本変換を実装します。
import java.util.Locale;
public final class SnakeCases {
private SnakeCases() {}
public static String toSnake(String text) {
if (text == null || text.isEmpty()) {
return text;
}
// 1. "userName" → "user_Name" のように、境目にアンダースコアを挟む
String withUnderscore = text.replaceAll("([a-z0-9])([A-Z])", "$1_$2");
// 2. 全体を小文字にする
return withUnderscore.toLowerCase(Locale.ROOT);
}
}
Java使い方はこうです。
System.out.println(SnakeCases.toSnake("userName")); // user_name
System.out.println(SnakeCases.toSnake("UserName")); // user_name
System.out.println(SnakeCases.toSnake("createdAt")); // created_at
System.out.println(SnakeCases.toSnake("userID")); // user_id
System.out.println(SnakeCases.toSnake("URLValue")); // url_value
Javaここで深掘りしたい重要ポイントは二つあります。
一つ目は、「([a-z0-9])([A-Z]) という正規表現で、“小文字または数字の直後に大文字が来る場所”を見つけている」ことです。userName なら rN のところでマッチし、$1_$2 によって r_Name になります。createdAt なら dA のところで d_At になります。
二つ目は、「アンダースコアを挟んだあとで、全体を小文字にしている」ことです。UserName のように先頭が大文字でも、User_Name → user_name となり、URLValue のような略語も URL_Value → url_value という形に落ち着きます。
この「境目に _ を挟んでから、小文字に落とす」という二段構えを覚えておくと、
キャメルケース → スネークケース変換のロジックが頭の中でスッと整理されます。
実装ステップ2:SCREAMING_SNAKE_CASE に変換する
snake_case をそのまま大文字にするだけでいい
USER_NAME のような SCREAMING_SNAKE_CASE は、
「snake_case を全部大文字にしたもの」と考えるとシンプルです。
import java.util.Locale;
public final class SnakeCases {
private SnakeCases() {}
public static String toSnake(String text) {
if (text == null || text.isEmpty()) {
return text;
}
String withUnderscore = text.replaceAll("([a-z0-9])([A-Z])", "$1_$2");
return withUnderscore.toLowerCase(Locale.ROOT);
}
public static String toScreamingSnake(String text) {
String snake = toSnake(text);
if (snake == null) {
return null;
}
return snake.toUpperCase(Locale.ROOT);
}
}
Java使い方はこうです。
System.out.println(SnakeCases.toScreamingSnake("userName")); // USER_NAME
System.out.println(SnakeCases.toScreamingSnake("createdAt")); // CREATED_AT
System.out.println(SnakeCases.toScreamingSnake("userID")); // USER_ID
Javaここでのポイントは、「SCREAMING_SNAKE_CASE は“snake_case のバリエーション”として扱う」ことです。toSnake を土台にして、その結果を大文字にするだけにしておくと、
ロジックが一箇所にまとまり、メンテナンスしやすくなります。
例題:Java フィールド名から DB カラム名を作る
userName → user_name を自動でやりたい
実務で一番よくあるのが、「Java のフィールド名は userName だけど、DB のカラム名は user_name」というパターンです。
マッピングライブラリを使わない場合でも、「名前変換ルール」だけ自前で持っておきたいことがあります。
public final class ColumnNames {
private ColumnNames() {}
public static String fieldToColumn(String fieldName) {
return SnakeCases.toSnake(fieldName);
}
}
Java使い方はこうです。
System.out.println(ColumnNames.fieldToColumn("userName")); // user_name
System.out.println(ColumnNames.fieldToColumn("createdAt")); // created_at
System.out.println(ColumnNames.fieldToColumn("userId")); // user_id
Javaここでの重要ポイントは、「“フィールド名→カラム名”という文脈をメソッド名に刻んでいる」ことです。
中身は単に toSnake を呼んでいるだけですが、fieldToColumn という名前がついているだけで、「これはDBとの橋渡しなんだな」と一目で分かります。
例題:フィールド名から環境変数名(SCREAMING_SNAKE_CASE)を作る
userName → USER_NAME のような変換
設定クラスのフィールド名を、そのまま環境変数名にマッピングしたい、というケースもよくあります。
public final class EnvNames {
private EnvNames() {}
public static String fieldToEnv(String fieldName) {
return SnakeCases.toScreamingSnake(fieldName);
}
}
Java使い方はこうです。
System.out.println(EnvNames.fieldToEnv("userName")); // USER_NAME
System.out.println(EnvNames.fieldToEnv("dbUrl")); // DB_URL
System.out.println(EnvNames.fieldToEnv("maxRetryCount"));// MAX_RETRY_COUNT
Javaここでのポイントは、「“環境変数は SCREAMING_SNAKE_CASE で書く”というルールをコードに落とし込んでいる」ことです。
プロジェクト全体でこのユーティリティを使えば、
「このフィールドはどんな環境変数名で上書きできるのか」が、自然と一貫した形になります。
例題:JSON のキー名を snake_case にそろえる
Java のプロパティ名をそのまま JSON のキーに使いたくないとき
API の仕様で、「JSON のキーは snake_case で書く」というルールになっていることがあります。
その場合、Java のプロパティ名(userName)から JSON のキー名(user_name)を作るユーティリティがあると便利です。
public final class JsonKeys {
private JsonKeys() {}
public static String fieldToJsonKey(String fieldName) {
return SnakeCases.toSnake(fieldName);
}
}
Java使い方はこうです。
System.out.println(JsonKeys.fieldToJsonKey("userName")); // user_name
System.out.println(JsonKeys.fieldToJsonKey("createdAt")); // created_at
Javaここでのポイントは、「“JSON のキー名は snake_case”という仕様を、ユーティリティ名と変換ロジックで固定している」ことです。
あとから「やっぱり camelCase にしたい」となったら、fieldToJsonKey の中身だけ差し替えれば、呼び出し側のコードはそのままで仕様変更に追従できます。
エッジケースと設計のポイント
すでに snake_case の文字列が来たらどうするか
入力がすでに user_name だった場合、toSnake("user_name") はどうなるか。
正規表現は「小文字+大文字」の境目だけを対象にしているので、user_name はそのまま user_name として返ってきます。
これは、「“すでに snake_case っぽいものは壊さない”」という意味で、実務的には良い挙動です。
略語(URL, ID, HTTP)をどう扱うか
userID → user_idURLValue → url_value
このあたりは、「略語を全部大文字で書くかどうか」によって好みが分かれます。
今の実装では、URLValue → URL_Value → url_value という流れになります。
もし「URLValue は url_value ではなく urlvalue にしたい」などの強いルールがあるなら、
略語リストを持っておいて、変換前に置き換える、といった工夫が必要になります。
大事なのは、「スネークケース変換は“命名規約をコードに落とし込んだもの”であり、プロジェクトごとのルールを反映させていく余地がある」と理解しておくことです。
まとめ:スネークケース変換ユーティリティで身につけたい感覚
スネークケース変換は、「Java の世界の名前(userName, createdAt)を、DB や設定・JSON の世界の名前(user_name, USER_NAME)に橋渡しする」ための技です。
押さえておきたい感覚は、まず「小文字(または数字)と大文字の境目に _ を挟み、そのあとで小文字に落とす」という二段構えのパターン。
次に、「toSnake を土台にして、toScreamingSnake のようなバリエーション(環境変数用など)を重ねる」という設計。
そして、「fieldToColumn や fieldToEnv、fieldToJsonKey のような“文脈付きの薄いラッパー”を用意して、命名規約をユーティリティとしてプロジェクト全体で共有する」ことです。
もしあなたのコードのどこかに、replaceAll("([a-z])([A-Z])", "$1_$2") のような断片がバラバラに散らばっているなら、
それを題材にして、ここで作った SnakeCases や ColumnNames、EnvNames、JsonKeys にまとめてみてください。
それだけで、「読みやすくて、再利用できて、命名ルールがコードとして生きている」文字列処理に、一段レベルアップできます。
