Flutterでe-StatのAPIを呼んでみた

e-Statとは各府省が公表する統計データをまとめているポータルサイトです。サイト上でデータが閲覧できるだけでなく、APIでそのデータを取得することができます。
Flutterでe-StatのAPIを呼ぶ処理を実装してみました。

スポンサーリンク

e-Statとは

「政府統計の総合窓口(e-Stat)」は、各府省が公表する統計データを一つにまとめ、統計データの検索をはじめとした、さまざまな機能を備えた政府統計のポータルサイトです。

知りたい統計データを簡単に検索して、パソコンにダウンロードできるほか、データベース化されたデータを使って人口ピラミッドなどのグラフを作成する機能、統計データを地図上に表示する機能など、ユーザーのニーズの高い機能を数多く備えた便利なサイトです。

引用:総務省統計局の統計局ホームページ

政府統計の総合窓口(e-Stat)ってなんだろう?

APIを利用することが可能です!
機能概要 | 政府統計の総合窓口(e-Stat)−API機能
アプリケーションIDを取得する必要があります。またe-StatのAPIを利用したアプリを公開する場合はクレジット表記する必要があります。

利用する統計表

e-Statには様々なデータがあります。
すべて | 統計データを探す | 政府統計の総合窓口

国土・気象、人口・世帯、労働・賃金などありますが、今回は以下を利用しました。
人口-総人口,日本人人口 | 統計表・グラフ表示 | 政府統計の総合窓口
都道府県別の人口を取得することができます。

この統計表にAPIでアクセスするURLは以下のような形式です。(JSONでレスポンスを取得する場合)

https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData?appId=[アプリケーションID]&lang=J&statsDataId=0003001298&metaGetFlg=Y&cntGetFlg=N&explanationGetFlg=N&annotationGetFlg=Y&replaceSpChars=0&sectionHeaderFlg=1

※アプリケーションIDを取得する必要があります

またこの統計表のIDは0003001298なのですが、統計表ID、アプリケーションIDを入力することでAPIのレスポンスを確認するツールが用意されていますので色々な統計表を探して試すことが可能です!

統計データ取得

※統計表のIDは各統計表のページのURL末尾で取得可能です。
人口-総人口,日本人人口 | 統計表・グラフ表示 | 政府統計の総合窓口の場合は、
https://www.e-stat.go.jp/dbview?sid=0003001298
0003001298が統計表のIDです。

Flutterの実装

DartPadで実装してみると以下のようなUIが表示される実装を行ってみました。
(アプリケーションIDを公表できないので、ブログには埋め込んでいません)

以前書いた以下の記事のソースを改造して利用しています。

それではソースを紹介します。リストボックスで都道府県を選択してボタンをクリックすると、APIから取得したデータをテーブルに記載します。

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

//const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(ApiCall());
}

class ApiCall extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _ApiCallState();
  }
}

class _ApiCallState extends State<ApiCall> {
  List<Map> dataList = []; //テーブルに表示するデータを格納するリスト
  //リストボックスの値設定
  final Map<String, String> _locationMap = {
    '00000': '全国',
    '13000': '東京',
    '12000': '千葉',
    '14000': '神奈川',
    '11000': '埼玉',
  };
  String _selectedArea = '00000'; //リストボックスの初期値

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        //ダークモード
        /*
        theme: ThemeData.dark().copyWith(
          scaffoldBackgroundColor: darkBlue,
        ),
        */
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            body: Center(
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[
              MyWidget(),
              const Text('都道府県を選択してください'),
              DropdownButton(
                value: _selectedArea,
                onChanged: (String? newValue) {
                  setState(() {
                    _selectedArea = newValue!;
                  });
                },
                items: _locationMap.entries.map((entry) {
                  return DropdownMenuItem(
                    child: Text(entry.value),
                    value: entry.key,
                  );
                }).toList(),
              ),
              //検索を実行するボタン
              ElevatedButton(
                  //fetchBookメソッドを呼んでeStat APIにリクエスト
                  onPressed: () => fetchEStat(_selectedArea)
                      //レスポンスを_apiInfoメソッドで処理
                      .then((value) => _apiInfo(value)),
                  child: const Text(
                    '人口推計を検索する',
                  )),
              //テーブルを記載する
              FittedBox(
                  child: DataTable(
                //ヘッダー設定。5列のテーブル
                columns: const <DataColumn>[
                  DataColumn(
                    label: Text('cat01'),
                  ),
                  DataColumn(
                    label: Text('cat02'),
                  ),
                  DataColumn(
                    label: Text('area'),
                  ),
                  DataColumn(
                    label: Text('time'),
                  ),
                  DataColumn(
                    label: Text('\$'),
                  ),
                ],
                //データはcreateRowListメソッドで設定
                rows: createRowList(),
              ))
            ]))));
  }

  //Google Book APIにリクエストする
  Future<EStat> fetchEStat(String area) async {
    String baseUrl = 'https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData?';
    String appId = '[取得したアプリケーションIDを記載してください]'; //アプリケーションID
    String statsDataId = '0003001298'; //統計表ID(人口推計 平成19年10月1日現在推計人口)
    String cdArea = area; //都道府県の設定(リストボックスの値を設定)
    String cdCat01 = '000'; //「男女別」の指定を"男女計"に設定
    String cdCat02 = '002'; //「人口」の指定を"日本人人口"に設定
    //その他のパラメータ
    String otherParam =
        '&lang=J&metaGetFlg=Y&cntGetFlg=N&explanationGetFlg=N&annotationGetFlg=Y&replaceSpChars=0&sectionHeaderFlg=1';
    //APIにリクエストするURL
    String url = baseUrl +
        'appId=' +
        appId +
        '&statsDataId=' +
        statsDataId +
        '&cdArea=' +
        cdArea +
        '&cdCat01=' +
        cdCat01 +
        '&cdCat02=' +
        cdCat02 +
        otherParam;
    url = Uri.encodeFull(url);

    //APIにリクエスト
    final response = await http.get(Uri.parse(url));

    //リクエスト後の処理
    if (response.statusCode == 200) {
      //レスポンスが正常だったら
      //レスポンスのJSONを加工してEStatオブジェクトを返す
      return EStat.fromJson(jsonDecode(response.body));
    } else {
      //レスポンスが異常だったら
      //例外を投げる
      throw Exception('Failed to load eStat');
    }
  }

  //eStat APIのレスポンスを処理する
  void _apiInfo(EStat data) {
    //テーブルに表示するvalueの要素をMapオブジェクトに設定
    dataList = [];
    Map dm;
    for (var i = 0; i < data.value.length; i++) {
      dm = {};
      dm['@cat01'] = data.value[i]['@cat01'] ?? '';
      dm['@cat02'] = data.value[i]['@cat02'] ?? '';
      dm['@area'] = data.value[i]['@area'] ?? '';
      dm['@time'] = data.value[i]['@time'] ?? '';
      dm['\$'] = data.value[i]['\$'] ?? '';
      dataList.add(dm);
    }

    //画面を更新する
    setState(() {
      rebuildAllChildren(context);
    });
  }

  //テーブルにデータを設定する
  List<DataRow> createRowList() {
    List<DataRow> dataRowList = [];
    List<DataCell> dataCellList;
    if (dataList.isNotEmpty) {
      for (Map m in dataList) {
        dataCellList = [];
        m.forEach((key, value) {
          dataCellList.add(DataCell(Text(value)));
        });
        dataRowList.add(DataRow(cells: [...dataCellList]));
      }
    }

    return dataRowList;
  }

  //画面を更新する
  void rebuildAllChildren(BuildContext context) {
    void rebuild(Element el) {
      el.markNeedsBuild();
      el.visitChildren(rebuild);
    }

    (context as Element).visitChildren(rebuild);
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      '都道府県の日本人人口',
      style: Theme.of(context).textTheme.headline4,
    );
  }
}

//eStat APIの結果を格納するクラス
class EStat {
  final int totalNumber;
  final List value;

  //コンストラクタ
  EStat({
    required this.totalNumber,
    required this.value,
  });

  //JSONからオブジェクト生成
  factory EStat.fromJson(Map<String, dynamic> json) {
    return EStat(
      totalNumber: json['GET_STATS_DATA']['STATISTICAL_DATA']['RESULT_INF']
          ['TOTAL_NUMBER'],
      value: json['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE'],
    );
  }
}
プロフィール
アラフィフでボルダリング、イラストなど挑戦中!
kakakuraをフォローする
アプリ開発
スポンサーリンク
       
kakakuraをフォローする
アラフィフガンバ
タイトルとURLをコピーしました