sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

C# PostcodeJP の API を利用して郵便番号から住所を取得する

f:id:shikaku_sh:20210823173353p:plain:w300

郵便番号から住所を取得するやり方のひとつに PostcodeJP がある。

郵便番号から住所を取得する API は、いくつか無料のものが公開されています。PostcodeJP も無料で利用できますが、ユーザー登録および API キーを利用することで、1日384回まで郵便番号の情報を取得できます。

郵便番号

郵便番号から住所などの情報を取得するサンプルはこんな感じ。

public class PostcodeClient
{
    private const string _BaseUrl = "https://apis.postcode-jp.com/";

    public static async Task<ApiResult> GetPostcodeAsync(string key, int postcode)
    {
        string postcodeUri = "api/v5/postcodes/";
        string url = _BaseUrl + postcodeUri + postcode.ToString("D7"); // 7桁
        string response = await GetHttpResponse(key, url);

        ApiResult[]? result = null;

        if (response != null)
        {
            var options = new JsonSerializerOptions();

            result = JsonSerializer.Deserialize<ApiResult[]>(response, options);
        }

        return (result?.Count() ?? 0) == 1 ? result?[0] ?? new () : new ();
    }

    private static async Task<string> GetHttpResponse(string key, string url)
    {
        using (var client = new HttpClient())
        {
            // client.DefaultRequestHeaders.Add("-G", $"-v \\");
            client.DefaultRequestHeaders.Add("-d", $"apiKey={key}");
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            var response1 = await client.GetAsync(url);
            var response2 = await response1.Content.ReadAsStringAsync();

            return response2;
        }
    }
}

以下のような API からは以下の JSON データが返却されるので、丁度良いクラスで受け取るとよいです。

https://apis.postcode-jp.com/api/v5/postcodes/xxxxxxx?apiKey=zzzzzzzz 形式でも動作しますが、HTTP ヘッダーに API キーを設定すると、SSL/TLS により API キーが保護されるはずです。

[
  {
    "prefCode": "13",
    "cityCode": "402",
    "postcode": "1001701",
    "oldPostcode": "10017",
    "pref": "東京都",
    "city": "青ヶ島村",
    "town": "",
    "allAddress": "東京都青ヶ島村",
    "hiragana": {
      "pref": "とうきょうと",
      "city": "あおがしまむら",
      "town": "",
      "allAddress": "とうきょうとあおがしまむら"
    },
    "halfWidthKana": {
      "pref": "トウキョウト",
      "city": "アオガシマムラ",
      "town": "",
      "allAddress": "トウキョウトアオガシマムラ"
    },
    "fullWidthKana": {
      "pref": "トウキョウト",
      "city": "アオガシマムラ",
      "town": "",
      "allAddress": "トウキョウトアオガシマムラ"
    },
    "generalPostcode": true,
    "officePostcode": false,
    "location": {
      "latitude": 32.45510482788086,
      "longitude": 139.76348876953125
    }
  }
]

最初は [] で始まっているため、コレクション(配列)の返却になっています。

JSON 対応クラスの例

public class ApiResult
{
    [JsonPropertyName("prefCode")]
    public string PrefectureCode { get; set; } = "";

    [JsonPropertyName("cityCode")]
    public string CityCode { get; set; } = "";

    [JsonPropertyName("postcode")]
    public string PostCode { get; set; } = "";

    [JsonPropertyName("oldPostcode")]
    public string OldPostCode { get; set; } = "";

    [JsonPropertyName("pref")]
    public string Prefecture { get; set; } = "";

    [JsonPropertyName("city")]
    public string City { get; set; } = "";

    [JsonPropertyName("town")]
    public string Town { get; set; } = "";

    [JsonPropertyName("allAddress")]
    public string Address { get; set; } = "";

    [JsonPropertyName("hiragana")]
    public Ruby Hiragana { get; set; } = new ();

    [JsonPropertyName("halfWidthKana")]
    public Ruby KanaHalf { get; set; } = new ();

    [JsonPropertyName("fullWidthKana")]
    public Ruby Katakana { get; set; } = new ();

    [JsonPropertyName("generalPostcode")]
    public bool IsGeneral { get; set; }

    [JsonPropertyName("officePostcode")]
    public bool IsOffice { get; set; }

    [JsonPropertyName("location")]
    public Location Location { get; set; } = new ();
}
public class Location
{
    [JsonPropertyName("latitude")]
    public double? Latitude { get; set; }
    [JsonPropertyName("longitude")]
    public double? Longitude { get; set; }
}

public class Ruby
{
    [JsonPropertyName("pref")]
    public string Prefecture { get; set; } = "";

    [JsonPropertyName("city")]
    public string City { get; set; } = "";

    [JsonPropertyName("town")]
    public string Town { get; set; } = "";

    [JsonPropertyName("allAddress")]
    public string Address { get; set; } = "";
}

テスト

PostcodeJP API を利用するためには、ユーザーごとの API キーが必要です。 API キーの管理については、過去に記述したとおり、アプリケーションでの利用に気をつけてください。

安易に API キーをコード中に含めないことを強く推奨します。(テストコードでも)

public class Tests
{
    private string ApiKey { get; set; } = "";

    [OneTimeSetUp]
    public void OneTimeSetUp()
    {
        // var api = Environment.GetEnvironmentVariable("RESAS_API", EnvironmentVariableTarget.User);
        DotNetEnv.Env.Load(".env");
        var key = DotNetEnv.Env.GetString("POSTCODE_API");

        ApiKey = key;
    }

    [TestCase(1001701, "東京都青ヶ島村")]
    [TestCase(0121100, "秋田県雄勝郡羽後町")]
    public async Task 郵便番号_To_住所(int postcode, string address)
    {
        var result = await PostcodeClient.GetResourceAsync(ApiKey, postcode);

        Assert.AreEqual(result.Address, address);
    }
}

例外のテストも追加したほうがよい。

サンプル

GitHub にサンプルを公開しています。

参考