はじめに 「ケバブケース変換」は“フロントエンド世界との共通語”
C# の世界では UserName(PascalCase)や userName(camelCase)が主流ですが、
フロントエンドや一部の Web API の世界では、user-name のような「kebab-case(ケバブケース)」がよく使われます。
CSS のプロパティ名(background-color)
一部の REST API のパラメータ(user-id)
JavaScript のオプション名や設定ファイル
こういう「ケバブケース文化」と、C# の PascalCase/camelCase の間をつないでくれるのが、
「ケバブケース変換ユーティリティ」です。
ここでは、プログラミング初心者向けに、
ケバブケースとは何か
PascalCase/camelCase から kebab-case への変換ルール
実務で使える変換ユーティリティの実装
略語(ID, URL など)や null への安全な対応
を、例題付きでかみ砕いて説明していきます。
ケバブケースのルールを言葉で整理する
まず、「kebab-case(ケバブケース)」を言葉で定義しておきます。
すべて小文字で書く。
単語の区切りはハイフン - でつなぐ。
例としては、
user-nameorder-idcreated-at
などです。
snake_case(user_name)との違いは、「区切りが _ か - か」だけです。
つまり、「snake_case 変換が分かれば、ケバブケース変換もほぼ同じノリで書ける」と思って大丈夫です。
PascalCase/camelCase → kebab-case の基本アルゴリズム
考え方のベースは「スネークケース変換」と同じ
UserName や userName を user-name にしたいとき、やりたいことはこうです。
文字列を左から 1 文字ずつ見る。
「小文字 → 大文字」に切り替わるところを「単語の境目」とみなす。
境目の前に - を挟む。
最後に全部小文字にする。
snake_case のときは _ を挟みましたが、ここではそれを - に変えるだけです。
まずはシンプル実装から
using System;
using System.Text;
public static class KebabCaseConverter
{
public static string ToKebabCase(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return string.Empty;
}
string trimmed = value.Trim();
var sb = new StringBuilder();
char[] chars = trimmed.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
char c = chars[i];
bool isUpper = char.IsUpper(c);
if (i > 0 && isUpper)
{
char prev = chars[i - 1];
bool prevIsLower = char.IsLower(prev);
bool prevIsDigit = char.IsDigit(prev);
if (prevIsLower || prevIsDigit)
{
sb.Append('-');
}
}
sb.Append(char.ToLowerInvariant(c));
}
return sb.ToString();
}
}
C#ここでの重要ポイントは次の通りです。
null や空白だけの入力は、例外にせず空文字にそろえる。
前後の空白は Trim() で落としてから処理する。
「現在の文字が大文字」かつ「直前が小文字または数字」のときだけ - を挟む。
最後に char.ToLowerInvariant で小文字にそろえる。
このルールだけで、かなり自然な kebab-case に変換できます。
動作確認とパターン別の挙動
代表的な例を試してみる
Console.WriteLine(KebabCaseConverter.ToKebabCase("UserName")); // user-name
Console.WriteLine(KebabCaseConverter.ToKebabCase("userName")); // user-name
Console.WriteLine(KebabCaseConverter.ToKebabCase("OrderID")); // order-id
Console.WriteLine(KebabCaseConverter.ToKebabCase("CreatedAt")); // created-at
Console.WriteLine(KebabCaseConverter.ToKebabCase("URL")); // url
Console.WriteLine(KebabCaseConverter.ToKebabCase("User1Name")); // user1-name
Console.WriteLine(KebabCaseConverter.ToKebabCase(" UserName ")); // user-name
Console.WriteLine(KebabCaseConverter.ToKebabCase(null)); // 空文字
C#ここでの挙動を少し深掘りします。
UserName → user-nameUser と Name の境目(r → N)で - を挟んでいます。
userName → user-name
先頭が小文字でも同じルールで動きます。
OrderID → order-idOrder と ID の境目(r → I)で - を挟み、ID は 1 単語として扱われます。
URL → url
全部大文字なので、途中に境目がないとみなして、そのまま 1 単語として小文字化します。
User1Name → user1-name1 は数字なので、「数字 → 大文字」の境目でも - を挟んでいます。
この挙動は、CSS や多くの Web API の命名とかなり相性が良いです。
略語(ID, URL, API など)をどう扱うか
「全部大文字のブロックは 1 単語」とみなす
OrderID や URLPath のような名前は、略語が絡む典型パターンです。
今の実装だと、
OrderID → order-idURLPath → url-path
となります。
URLPath の場合、「URL」が 1 ブロック、「Path」が 1 ブロックとして扱われ、
その境目に - が入るイメージです。
多くの実務では、この挙動で十分自然です。
もし、「URLPath を urlpath にしたい」といった特殊な要件があるなら、
それは個別の例外ルールとして別途処理する必要がありますが、
汎用ユーティリティとしては、今のルールがバランスの良い落としどころです。
既に snake_case のものを kebab-case にしたい場合
_ を - に置き換えるだけで済むケース
すでに user_name のような snake_case になっている文字列を、user-name にしたいだけなら、話はもっとシンプルです。
やることは、
全部小文字にそろえる(念のため)_ を - に置き換える
だけです。
public static class KebabCaseConverter
{
public static string SnakeToKebab(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return string.Empty;
}
string lower = value.Trim().ToLowerInvariant();
return lower.Replace('_', '-');
}
}
C#例です。
Console.WriteLine(KebabCaseConverter.SnakeToKebab("user_name")); // user-name
Console.WriteLine(KebabCaseConverter.SnakeToKebab("USER_ID")); // user-id
Console.WriteLine(KebabCaseConverter.SnakeToKebab(" created_at ")); // created-at
C#「DB のカラム名(snake_case)を、そのまま API のパラメータ名(kebab-case)にしたい」
といった場面では、このくらいのユーティリティで十分です。
実務での使いどころと設計のポイント
どこで kebab-case に変換するかを決める
ケバブケース変換も、「どの層でやるか」を決めておくと設計がスッキリします。
フロントエンド向けの API を作るとき。
内部では PascalCase/camelCase で持っておき、
JSON のキーやクエリパラメータを組み立てる直前で kebab-case に変換する。
設定ファイルやオプション名を扱うとき。
C# のプロパティ名は PascalCase のままにしておき、
設定ファイル側のキー(kebab-case)とのマッピングに変換ユーティリティを使う。
例えば、こんなイメージです。
string propertyName = "UserName";
string optionKey = KebabCaseConverter.ToKebabCase(propertyName); // user-name
// 設定ファイルから "user-name" を探す、など
C#「C# の世界の命名」と「外の世界の命名」を、
ケバブケース変換ユーティリティで橋渡しするイメージを持っておくと、
どこに置くべき処理かが見えやすくなります。
まとめ 「ケバブケース変換ユーティリティ」は“フロントとバックの言語通訳”
kebab-case 変換は、単なる記号遊びではなく、
「C#(PascalCase/camelCase)と、フロントエンドや外部APIの命名ルールの違いを吸収する通訳」
として機能します。
押さえておきたいポイントはこうです。
kebab-case は「全部小文字+単語区切りは -」というシンプルなルール。
PascalCase/camelCase → kebab-case は、「大文字の前に - を挟んで、最後に全部小文字にする」ロジックで実装できる。
null や空白だけの入力は、例外にせず空文字にそろえると、呼び出し側が楽になる。
略語(ID, URL など)は、「全部大文字のブロックは 1 単語」とみなすシンプルなルールで、多くの実務ケースをカバーできる。
「どの層で kebab-case に変換するか」(API 出力、設定ファイルとのマッピングなど)を決めておくと、命名の一貫性が保ちやすい。
ここまで理解できれば、「手で user-name と書いている」段階から一歩進んで、
「C# の名前から自動で kebab-case を生成する」実務的なユーティリティを、自分の手で設計・実装できるようになっていきます。
