Java Tips | 文字列処理:ケバブケース変換

Java Java
スポンサーリンク

ケバブケース変換は「Java の名前を“URL やフロントエンドの世界”に合わせる」技

ここまで出てきたキャメルケース(userName)、スネークケース(user_name)に続いて、
フロントエンドや URL でよく使われるのが ケバブケース(kebab-case) です。

user-name
user-profile-image
created-at

といった、「単語をハイフン - でつなぐ」スタイルですね。
REST API のパス、フロントエンドのコンポーネント名、CSS のクラス名などでよく見かけます。

Java の世界ではキャメルケースが主流なので、
userNameuser-name」のように変換できるユーティリティを持っておくと、
バックエンドとフロントエンド、Java と URL の橋渡しがとても楽になります。


ケバブケースの基本イメージと使いどころ

kebab-case と lower-kebab-case

ケバブケースは、単語をハイフンでつなぐ書き方です。
一般的には、すべて小文字で書く lower-kebab-case がよく使われます。

user-name
user-profile
max-retry-count

URL パスや JSON のキー、CSS クラス名などで「読みやすくて、目に優しい」命名として好まれます。
今回のユーティリティでは、

  • camelCase / PascalCase → kebab-case(小文字)

を軸にして実装していきます。


基本方針:「スネークケースと同じ発想で、区切り文字だけ変える」

「大文字の境目に区切りを入れる」という考え方は同じ

キャメルケース → スネークケース変換では、
「小文字+大文字の境目に _ を挟む」という発想でした。

ケバブケースも本質は同じで、
「小文字+大文字の境目に - を挟む」だけです。

userNameuser-Name → 小文字化 → user-name
createdAtcreated-At → 小文字化 → created-at

つまり、スネークケース変換のロジックをほぼそのまま流用しつつ、
「アンダースコア _ をハイフン - に変える」だけで実現できます。


実装:キャメルケースを kebab-case に変換する

正規表現で「小文字と大文字の境目」にハイフンを挟む

まずは、userNameuser-name のような基本変換を実装します。

import java.util.Locale;

public final class KebabCases {

    private KebabCases() {}

    public static String toKebab(String text) {
        if (text == null || text.isEmpty()) {
            return text;
        }
        // 1. "userName" → "user-Name" のように、境目にハイフンを挟む
        String withHyphen = text.replaceAll("([a-z0-9])([A-Z])", "$1-$2");
        // 2. 全体を小文字にする
        return withHyphen.toLowerCase(Locale.ROOT);
    }
}
Java

使い方はこうなります。

System.out.println(KebabCases.toKebab("userName"));      // user-name
System.out.println(KebabCases.toKebab("UserName"));      // user-name
System.out.println(KebabCases.toKebab("createdAt"));     // created-at
System.out.println(KebabCases.toKebab("userID"));        // user-id
System.out.println(KebabCases.toKebab("URLValue"));      // url-value
Java

ここで深掘りしたい重要ポイントは二つです。

一つ目は、「([a-z0-9])([A-Z]) という正規表現で、“小文字または数字の直後に大文字が来る場所”を見つけている」ことです。
userName なら rN のところでマッチし、$1-$2 によって r-Name になります。
createdAt なら dA のところで d-At になります。

二つ目は、「ハイフンを挟んだあとで、全体を小文字にしている」ことです。
UserName のように先頭が大文字でも、User-Nameuser-name となり、
URLValue のような略語も URL-Valueurl-value という形に落ち着きます。

この「境目に - を挟んでから、小文字に落とす」という二段構えを覚えておくと、
キャメルケース → ケバブケース変換のロジックがとてもシンプルに見えてきます。


例題:Java のフィールド名から URL パス用のセグメント名を作る

userName → /user-name のような変換

REST API の設計で、URL パスをケバブケースで書きたいことがあります。

/user-name
/user-profile
/max-retry-count

このとき、「Java のメソッド名やフィールド名から URL セグメントを作る」ユーティリティがあると便利です。

public final class UrlSegments {

    private UrlSegments() {}

    public static String fieldToSegment(String fieldName) {
        String kebab = KebabCases.toKebab(fieldName);
        if (kebab == null || kebab.isEmpty()) {
            return "";
        }
        return "/" + kebab;
    }
}
Java

使い方はこうです。

System.out.println(UrlSegments.fieldToSegment("userName"));      // /user-name
System.out.println(UrlSegments.fieldToSegment("userProfile"));   // /user-profile
System.out.println(UrlSegments.fieldToSegment("maxRetryCount")); // /max-retry-count
Java

ここでのポイントは、「“URL セグメント用”という文脈をメソッド名に刻んでいる」ことです。
中身は単に toKebab を呼んでいるだけですが、
fieldToSegment という名前がついているだけで、「これはURLパス用なんだな」と一目で分かります。


例題:Java のプロパティ名からフロントエンド用のキー名を作る

userName → user-name を JSON や設定のキーに使う

フロントエンド側のコードや設定ファイルで、
「キー名はケバブケースで書く」というルールにしているプロジェクトもあります。

その場合、Java のプロパティ名からケバブケースのキー名を作るユーティリティがあると、
バックエンドとフロントエンドの橋渡しがスムーズになります。

public final class FrontKeys {

    private FrontKeys() {}

    public static String fieldToFrontKey(String fieldName) {
        return KebabCases.toKebab(fieldName);
    }
}
Java

使い方はこうです。

System.out.println(FrontKeys.fieldToFrontKey("userName"));      // user-name
System.out.println(FrontKeys.fieldToFrontKey("createdAt"));     // created-at
System.out.println(FrontKeys.fieldToFrontKey("profileImageUrl"));// profile-image-url
Java

ここでのポイントは、「“フロントエンド用のキー名”という意図を、ユーティリティ名で表現している」ことです。
あとから「やっぱり snake_case にしたい」となったら、
fieldToFrontKey の中身だけ差し替えれば、呼び出し側のコードはそのままで仕様変更に追従できます。


例題:CSS クラス名やコンポーネント名をケバブケースにそろえる

UserProfileCard → user-profile-card のような変換

フロントエンドの世界では、CSS クラス名や Web コンポーネント名をケバブケースで書くことが多いです。

user-profile-card
app-header-bar

Java 側でテンプレートを生成するときに、クラス名やコンポーネント名をケバブケースに変換したい、という場面もあります。

public final class CssNames {

    private CssNames() {}

    public static String classNameToCss(String className) {
        return KebabCases.toKebab(className);
    }
}
Java

使い方はこうです。

System.out.println(CssNames.classNameToCss("UserProfileCard")); // user-profile-card
System.out.println(CssNames.classNameToCss("AppHeaderBar"));    // app-header-bar
Java

ここでのポイントは、「PascalCase(クラス名)も camelCase と同じロジックでケバブケースに落とせる」ことです。
UserProfileCardUser-Profile-Carduser-profile-card という流れで、
クラス名からそのまま CSS クラス名を作ることができます。


エッジケースと設計のポイント

すでに kebab-case の文字列が来たらどうするか

入力がすでに user-name だった場合、toKebab("user-name") はどうなるか。
正規表現は「小文字+大文字」の境目だけを対象にしているので、
user-name はそのまま user-name として返ってきます。

これは、「“すでにケバブケースっぽいものは壊さない”」という意味で、実務的には良い挙動です。

略語(URL, ID, HTTP)をどう扱うか

userIDuser-id
URLValueurl-value

このあたりは、スネークケースのときと同じく、「略語をどう扱うか」の設計ポイントです。
今の実装では、URLValueURL-Valueurl-value という流れになります。

もし「URLValueurlvalue にしたい」などの強いルールがあるなら、
略語リストを持っておいて、変換前に置き換える、といった工夫が必要になります。

大事なのは、「ケバブケース変換は“命名規約をコードに落とし込んだもの”であり、プロジェクトごとのルールを反映させていく余地がある」と理解しておくことです。


まとめ:ケバブケース変換ユーティリティで身につけたい感覚

ケバブケース変換は、「Java の世界の名前(userName, UserProfileCard)を、URL やフロントエンドの世界の名前(user-name, user-profile-card)に橋渡しする」ための技です。

押さえておきたい感覚は、まず「小文字(または数字)と大文字の境目に - を挟み、そのあとで小文字に落とす」という二段構えのパターン。
次に、「toKebab を土台にして、fieldToSegmentfieldToFrontKeyclassNameToCss のような“文脈付きの薄いラッパー”を用意し、URL・フロント・CSS などの命名規約をユーティリティとして共有する」こと。

もしあなたのコードのどこかに、replaceAll("([a-z])([A-Z])", "$1-$2") のような断片がバラバラに散らばっているなら、
それを題材にして、ここで作った KebabCasesUrlSegmentsFrontKeysCssNames にまとめてみてください。
それだけで、「読みやすくて、再利用できて、バックエンドとフロントエンドの命名がきれいにつながる」文字列処理に、一段レベルアップできます。

タイトルとURLをコピーしました