C# Tips | 文字列処理:キャメルケース変換

C# C#
スポンサーリンク

はじめに 「キャメルケース変換」は“名前をそろえるためのルールエンジン”

業務で C# を書いていると、「名前の書き方」をそろえたくなる場面がたくさん出てきます。
JSON のプロパティ名、API のパラメータ名、フロント側とのインターフェース、コード生成ツールの出力などです。

その中でよく出てくるのが「キャメルケース(camelCase)」です。
userNameorderIdcreatedAt のように、先頭が小文字で、単語の区切りを大文字で表現するスタイルですね。

ここでは、プログラミング初心者向けに、

キャメルケースとは何か
よくある入力形式(snake_case、PascalCase、スペース区切りなど)からの変換
実務で使える「キャメルケース変換ユーティリティ」の作り方
null や空文字、変な入力に対する安全な扱い方

を、例題付きでかみ砕いて説明していきます。


キャメルケースの基本ルールを言葉で整理する

まず、「キャメルケース」を言葉で定義しておきます。

1つ目の単語の先頭は小文字にする。
2つ目以降の単語の先頭は大文字にする。
単語の区切りにはアンダースコアやスペースを使わず、くっつけて書く。

例えば、user_name なら userName
ORDER_ID なら orderId
customer address なら customerAddress という形になります。

この「単語をどう区切るか」「どこを大文字にするか」をコードに落とし込んでいくのが、キャメルケース変換ユーティリティの役割です。


一番よくあるパターン snake_case → camelCase

snake_case を単語に分解する

まずは、user_nameorder_id のような「snake_case」からキャメルケースに変換するパターンです。

考え方はシンプルで、

アンダースコア _ で文字列を分割して単語の配列にする。
1つ目の単語は全部小文字にする。
2つ目以降の単語は、先頭を大文字、それ以外を小文字にする。
それらをくっつける。

これを C# で書くと、次のようになります。

using System;
using System.Globalization;

public static class CaseConverter
{
    public static string SnakeToCamel(string? value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return string.Empty;
        }

        string[] parts = value.Split('_', StringSplitOptions.RemoveEmptyEntries);

        if (parts.Length == 0)
        {
            return string.Empty;
        }

        TextInfo textInfo = CultureInfo.InvariantCulture.TextInfo;

        for (int i = 0; i < parts.Length; i++)
        {
            string p = parts[i].ToLowerInvariant();

            if (i == 0)
            {
                parts[i] = p;
            }
            else
            {
                if (p.Length == 0)
                {
                    parts[i] = string.Empty;
                }
                else
                {
                    parts[i] = textInfo.ToTitleCase(p);
                }
            }
        }

        return string.Concat(parts);
    }
}
C#

動き方を具体例で確認する

Console.WriteLine(CaseConverter.SnakeToCamel("user_name"));      // userName
Console.WriteLine(CaseConverter.SnakeToCamel("USER_ID"));        // userId
Console.WriteLine(CaseConverter.SnakeToCamel("customer_address"));// customerAddress
Console.WriteLine(CaseConverter.SnakeToCamel("  "));             // 空文字
Console.WriteLine(CaseConverter.SnakeToCamel(null));             // 空文字
C#

ここでの重要ポイントは次の通りです。

null や空白だけの文字列は、例外にせず空文字にそろえている。
Split のときに RemoveEmptyEntries を指定して、"user__name" のような連続アンダースコアを無視している。
ToLowerInvariant で一度全部小文字にしてから、2単語目以降だけ先頭を大文字にしている。

「まず全部小文字に落としてから、必要なところだけ大文字にする」という流れにしておくと、
USER_NAME のような入力でも安定して変換できます。


PascalCase → camelCase の変換

先頭だけ小文字にすればいいパターン

C# のプロパティ名やクラス名は、UserNameOrderId のような「PascalCase」が多いです。
これを JSON のプロパティ名などで userName にしたい、という場面もよくあります。

PascalCase から camelCase への変換は、ルールがとてもシンプルです。

先頭の1文字だけ小文字にする。
それ以外はそのまま。

これをユーティリティにすると、次のようになります。

public static class CaseConverter
{
    public static string PascalToCamel(string? value)
    {
        if (string.IsNullOrEmpty(value))
        {
            return string.Empty;
        }

        if (value.Length == 1)
        {
            return value.ToLowerInvariant();
        }

        string first = value.Substring(0, 1).ToLowerInvariant();
        string rest = value.Substring(1);

        return first + rest;
    }
}
C#

具体例で確認する

Console.WriteLine(CaseConverter.PascalToCamel("UserName")); // userName
Console.WriteLine(CaseConverter.PascalToCamel("X"));        // x
Console.WriteLine(CaseConverter.PascalToCamel("URL"));      // uRL
Console.WriteLine(CaseConverter.PascalToCamel(null));       // 空文字
C#

"URL""uRL" になるのは、一見違和感があるかもしれませんが、
「先頭だけ小文字にする」というルールに忠実に従った結果です。

もし、「頭字語(URL、ID など)は全部小文字にしたい」といった別ルールが必要なら、
そこは別途仕様として決めて、専用の処理を足すことになります。


スペース区切りやハイフン区切りからのキャメルケース変換

「単語を区切る記号」をパラメータ化する

実務では、user nameuser-name のような形式からキャメルケースにしたいこともあります。
snake_case のときと同じ発想で、

区切り文字で分割する。
1つ目の単語は小文字。
2つ目以降は先頭を大文字。

という処理をすればOKです。

汎用的にするなら、「区切り文字を配列で渡せる」ようにしておくと便利です。

using System;
using System.Globalization;

public static class CaseConverter
{
    public static string ToCamelFromSeparated(string? value, params char[] separators)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return string.Empty;
        }

        if (separators is null || separators.Length == 0)
        {
            separators = new[] { ' ' };
        }

        string[] parts = value.Split(separators, StringSplitOptions.RemoveEmptyEntries);

        if (parts.Length == 0)
        {
            return string.Empty;
        }

        TextInfo textInfo = CultureInfo.InvariantCulture.TextInfo;

        for (int i = 0; i < parts.Length; i++)
        {
            string p = parts[i].ToLowerInvariant();

            if (i == 0)
            {
                parts[i] = p;
            }
            else
            {
                if (p.Length == 0)
                {
                    parts[i] = string.Empty;
                }
                else
                {
                    parts[i] = textInfo.ToTitleCase(p);
                }
            }
        }

        return string.Concat(parts);
    }
}
C#

具体例

Console.WriteLine(CaseConverter.ToCamelFromSeparated("user name", ' '));      // userName
Console.WriteLine(CaseConverter.ToCamelFromSeparated("user-name", '-'));      // userName
Console.WriteLine(CaseConverter.ToCamelFromSeparated("USER NAME", ' '));      // userName
Console.WriteLine(CaseConverter.ToCamelFromSeparated("  customer  address ", ' ')); // customerAddress
C#

snake_case 版とほぼ同じロジックですが、「区切り文字を自由に変えられる」ようにしたことで、
いろいろな入力形式に対応できるようになっています。


実務で大事なポイント 「どこでキャメルケースにそろえるか」を決める

入力時にそろえるか、出力時にそろえるか

キャメルケース変換は、「いつやるか」を決めておくと設計がスッキリします。

入力時にそろえるパターン。
外部から入ってきた名前(snake_case やスペース区切りなど)を、
最初にキャメルケースに変換してから内部で扱う。

出力時にそろえるパターン。
内部では PascalCase や別形式で持っておき、
JSON やフロント向けに出すときだけキャメルケースに変換する。

例えば、JSON のプロパティ名をキャメルケースにしたい場合、
DTO のプロパティ名は PascalCase のままにしておいて、
シリアライズ時に「キャメルケースに変換するネーミングポリシー」を使う、というやり方もあります。

自前ユーティリティを使う場合でも、

「外から来た名前を正規化する層」
「外に出す名前を整形する層」

のどちらでキャメルケース変換を行うかを決めておくと、
同じ処理をあちこちで重複させずに済みます。


まとめ 「キャメルケース変換ユーティリティ」は“名前の揺れを吸収する小さな翻訳機”

キャメルケース変換は、見た目の問題だけでなく、
「システム間で名前のルールが違うときに、その差を吸収するための翻訳機」として機能します。

押さえておきたいポイントを整理すると、こうなります。

snake_case から camelCase への変換は、「区切りで分割→1単語目は小文字→2単語目以降は先頭だけ大文字」というパターンで書ける。
PascalCase から camelCase への変換は、「先頭1文字だけ小文字にする」というシンプルなルールで十分なことが多い。
null や空白だけの入力は、例外にせず空文字にそろえると、呼び出し側が楽になる。
スペース区切りやハイフン区切りなど、区切り文字をパラメータ化しておくと、いろいろな入力形式に対応できる。
「入力時にキャメルケースにそろえるか」「出力時にそろえるか」を設計として決めておくと、システム全体の一貫性が保ちやすい。

ここまで理解できれば、「なんとなく手で直している」状態から抜け出して、
「名前のルールの違いをコードで吸収する」ことができる、実務で使える C# ユーティリティを書けるようになっていきます。

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