🏙️

TypeScriptでRESAS-APIを利用する

2024/07/20に公開

はじめに

RESAS(Regional Economy and Society Analyzing System)は、日本の地域経済分析システムであり、内閣府のまち・ひと・しごと創生本部が提供する官民データ利活用のためのプラットフォームです。このAPIを使用することで、開発者は日本の様々な地域経済データにプログラムからアクセスできます。本記事では、TypeScriptを使用してRESAS-APIにアクセスする方法を詳しく解説します。

RESAS-APIの概要

RESAS-APIは以下のようなデータへのアクセスを提供しています:

  1. 人口動態:年齢別人口、人口増減、将来人口推計など
  2. 産業構造:産業別の売上高、従業者数、特化係数など
  3. 観光:宿泊者数、観光消費額、外国人観光客の動向など
  4. 農業:農産物の生産量、農業者の年齢構成、耕地面積など
  5. 消費動向:地域別の消費傾向、商業施設の分布など
  6. 自治体比較:様々な指標に基づく自治体間の比較データ

これらのデータは、地方自治体の政策立案、企業の事業戦略策定、学術研究など、幅広い分野で活用されています。

1. 準備

RESAS-APIを利用するための環境を整えましょう。

必要なパッケージのインストール

まず、必要なパッケージをインストールします。ターミナルで以下のコマンドを実行してください:

npm install node-fetch@2 https-proxy-agent
npm install --save-dev @types/node-fetch@2 @types/node

ここでは、node-fetchのバージョン2を使用しています。これは、Node.js環境でfetchを使用するためです。

環境変数の設定

RESAS-APIを使用するには、APIキーが必要です。セキュリティを考慮して、このAPIキーは環境変数として設定します。

プロジェクトのルートディレクトリに.envファイルを作成し、以下の内容を記述してください:

RESAS_API_KEY=あなたのAPIキー

必要に応じて、プロキシURLも設定できます:

HTTP_PROXY=プロキシURL

注意:.envファイルはバージョン管理システム(GitなVCSなど)から除外するようにしてください。

2. TypeScriptコードの実装

それでは、RESAS-APIにアクセスするためのTypeScriptコードを実装しましょう。以下のコードをsrc/utils/resasAPI.ts(またはあなたのプロジェクト構造に適した場所)に保存してください。

import { HttpsProxyAgent } from 'https-proxy-agent'
import fetch from 'node-fetch'

const RESAS_API_KEY = process.env.RESAS_API_KEY
const BASE_URL = 'https://opendata.resas-portal.go.jp'
const PROXY_URL = process.env.HTTP_PROXY

export interface ResasParamsType {
  url: string
  [key: string]: string | number | boolean // 追加のパラメータを許可
}

export interface ResasResponseType<T> {
  message: string | null
  result: T
}

export const fetchResasAPI = async <T>(
  resasParams: ResasParamsType
): Promise<ResasResponseType<T>> => {
  if (!RESAS_API_KEY) {
    throw new Error('環境変数に RESAS_API_KEY が設定されていません。')
  }

  try {
    const { url, ...params } = resasParams
    const paramString = new URLSearchParams(
      params as Record<string, string>
    ).toString()

    const fetchOptions: RequestInit = {
      method: 'GET',
      headers: {
        'X-API-KEY': RESAS_API_KEY,
      },
    }

    if (PROXY_URL) {
      fetchOptions.agent = new HttpsProxyAgent(PROXY_URL)
    }

    const response = await fetch(
      `${BASE_URL}/${url}?${paramString}`,
      fetchOptions
    )

    if (!response.ok) {
      throw new Error(
        `RESAS-APIへのリクエストが失敗しました: ${response.statusText}`
      )
    }

    const responseText = await response.text()
    const data = JSON.parse(responseText) as ResasResponseType<T>
    return data
  } catch (error) {
    console.error('RESAS-API データの取得中にエラーが発生しました:', error)
    throw error
  }
}

3. コードの詳細説明

このセクションでは、上記のコードの各部分を詳しく解説します。

インポートと定数

import { HttpsProxyAgent } from 'https-proxy-agent'
import fetch from 'node-fetch'

const RESAS_API_KEY = process.env.RESAS_API_KEY
const BASE_URL = 'https://opendata.resas-portal.go.jp'
const PROXY_URL = process.env.HTTP_PROXY

ここでは必要なモジュールをインポートし、環境変数からAPIキーとプロキシURLを取得しています。BASE_URLは RESAS-API のベースURLです。

インターフェース定義

export interface ResasParamsType {
  url: string
  [key: string]: string | number | boolean
}

export interface ResasResponseType<T> {
  message: string | null
  result: T
}

これらのインターフェースは、APIリクエストのパラメータとレスポンスの構造を定義しています。

  • ResasParamsType:

    • url: 必須のプロパティで、APIエンドポイントのパスを指定します。
    • [key: string]: string | number | boolean: インデックスシグネチャを使用して、追加のパラメータを許可しています。これにより、各APIエンドポイントに固有のパラメータを柔軟に追加できます。
  • ResasResponseType<T>:

    • message: APIからのメッセージ。通常はnullですが、エラー時にはエラーメッセージが含まれます。
    • result: APIから返されるデータ。ジェネリック型Tを使用することで、様々なAPIエンドポイントの結果に対応できます。

fetchResasAPI関数

export const fetchResasAPI = async <T>(
  resasParams: ResasParamsType
): Promise<ResasResponseType<T>> => {
  // ...
}

この関数は、RESAS-APIにリクエストを送信し、結果を取得します。ジェネリック型Tを使用することで、異なるAPIエンドポイントに対して型安全に使用できます。

エラーチェック

if (!RESAS_API_KEY) {
  throw new Error('環境変数に RESAS_API_KEY が設定されていません。')
}

APIキーが設定されていない場合、エラーをスローします。これにより、APIキーが正しく設定されていることを確認できます。

リクエストの準備

const { url, ...params } = resasParams
const paramString = new URLSearchParams(
  params as Record<string, string>
).toString()

URLパラメータを準備します。url以外のパラメータをURLSearchParamsを使用してクエリ文字列に変換します。これにより、複雑なパラメータも簡単にURLに追加できます。

フェッチオプションの設定

const fetchOptions: RequestInit = {
  method: 'GET',
  headers: {
    'X-API-KEY': RESAS_API_KEY,
  },
}

if (PROXY_URL) {
  fetchOptions.agent = new HttpsProxyAgent(PROXY_URL)
}

リクエストのオプションを設定します。APIキーをヘッダーに含め、プロキシが設定されている場合はHttpsProxyAgentを使用します。これにより、プロキシ環境下でも APIにアクセスできます。

リクエストの送信と応答の処理

const response = await fetch(
  `${BASE_URL}/${url}?${paramString}`,
  fetchOptions
)

if (!response.ok) {
  throw new Error(
    `RESAS-APIへのリクエストが失敗しました: ${response.statusText}`
  )
}

const responseText = await response.text()
const data = JSON.parse(responseText) as ResasResponseType<T>
return data

fetchを使用してリクエストを送信し、レスポンスを処理します。エラーの場合は例外をスローし、成功した場合はJSONデータを解析して返します。as ResasResponseType<T>を使用することで、レスポンスデータを適切な型にキャストしています。

4. 使用例

この関数は以下のように使用できます:

interface PrefectureData {
  prefCode: number
  prefName: string
}

async function getPrefectures() {
  try {
    const result = await fetchResasAPI<PrefectureData[]>({
      url: 'api/v1/prefectures',
    })
    console.log(result.result)
  } catch (error) {
    console.error('エラーが発生しました:', error)
  }
}

getPrefectures()

この例では、都道府県一覧を取得しています。fetchResasAPI関数にジェネリック型PrefectureData[]を指定することで、返される結果の型を明示的に定義しています。

より複雑な例として、特定の都道府県の人口構成を取得する場合は以下のようになります:

interface PopulationCompositionData {
  // APIの実際のレスポンス構造に合わせて定義
  year: number
  value: number
}

async function getPopulationComposition(prefCode: number) {
  try {
    const result = await fetchResasAPI<PopulationCompositionData[]>({
      url: 'api/v1/population/composition/perYear',
      prefCode: prefCode,
      cityCode: '-'
    })
    console.log(result.result)
  } catch (error) {
    console.error('エラーが発生しました:', error)
  }
}

getPopulationComposition(13) // 東京都のデータを取得

5. エラーハンドリング

この実装では、主に以下の2つの場合でエラーがスローされます:

  1. APIキーが設定されていない場合
  2. APIリクエストが失敗した場合(HTTPステータスコードが200以外)

これらのエラーは、関数を呼び出す側で適切に処理する必要があります。例えば:

try {
  const result = await fetchResasAPI<SomeDataType>({
    url: 'some/api/endpoint',
    // その他のパラメータ
  })
  // 結果を処理
} catch (error) {
  if (error instanceof Error) {
    console.error('APIエラー:', error.message)
    // ユーザーへのエラー表示やログ記録など、適切なエラー処理を行う
  } else {
    console.error('不明なエラーが発生しました')
  }
}

6. セキュリティ考慮事項

  1. APIキーの管理:

    • APIキーを環境変数として設定し、ソースコード内に直接記述しないようにしています。
    • 本番環境では、環境変数の設定を適切に行い、APIキーが外部に漏れないよう注意してください。
  2. HTTPS:

    • RESAS-APIは HTTPSを使用しているため、通信は暗号化されています。
  3. エラーメッセージ:

    • プロダクション環境では、詳細なエラーメッセージをクライアントに返さないよう注意してください。

まとめ

このTypeScriptコードを使用することで、RESAS-APIに型安全かつ効率的にアクセスできます。柔軟なパラメータ型定義により、様々なエンドポイントに対応でき、ジェネリック型を活用することで、異なる結果の構造にも適応できます。

RESAS-APIは日本の地域経済データへのアクセスを提供する強力なツールです。このコードを基盤として、地域経済分析ツールやデータ可視化アプリケーションなど、多様なプロジェクトを展開することができます。

サンプルコード

実際にRESAS-APIを活用したアプリを開発しています。

https://github.com/uruhayato373/statistics-japan/tree/main/src/utils/resas

Discussion