FlutterでJSONを詰め込むための構造体を簡単に作る方法
はじめに
Flutterアプリ開発では、JSONデータを取得し、Dartの構造体に変換することがよくあります。そんな時に役立つツール「JSON to Dart」をご紹介し、郵便番号検索APIを例に実際に使ってみたいと思います。
JSON to Dartの使い方
ここでは、JSON to Dartを使って取得したJSONデータをDartの構造体に変換する方法を説明します。
JsonファイルからそのJsonをDart構造体に詰め込むことができるコードを生成するサイトです。 これを使うことで、Jsonを取得できるWEBAPIを使ったアプリ開発がめっちゃやりやすくなります。
JSONデータの取得と変換
まずは郵便番号検索APIからJSONデータを取得し、JSON to Dartを使ってDartの構造体に変換します。変換後のコードはjson/JsonStruct.dartに配置されます。
https://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
取得したJsonをJson to Dartにかけていきます。
{
"message": null,
"results": [
{
"address1": "高知県",
"address2": "南国市",
"address3": "蛍が丘",
"kana1": "コウチケン",
"kana2": "ナンコクシ",
"kana3": "ホタルガオカ",
"prefcode": "39",
"zipcode": "7830060"
}
],
"status": 200
}
コード解説
この記事で紹介したコードは、以下のような構成になっています。
json/JsonStruct.dart: JSON to Dartで生成したDart構造体のコード models/logic.dart: APIからJSONデータを取得し、Dart構造体に変換するロジック view/ui.dart: 取得したデータを表示するUIコンポーネント
フォルダ構成
C:.
│ main.dart
│
├─json
│ JsonStruct.dart
│
├─models
│ logic.dart
│
└─view
ui.dart
json/JsonStruct.dart
ツールをかけて取得結果を貼り付け、一部コードを修正します。 (Null Safetyなどの兼ね合いで最新のDartだとエラーが出るため)
ほとんど変換しただけですが、とりあえず貼り付けます。
class Autogenerated {
Null message;
late List<Results> results;
late int status;
Autogenerated({this.message, required this.results, required this.status});
Autogenerated.fromJson(Map<String, dynamic> json) {
message = json['message'];
if (json['results'] != null) {
results = <Results>[];
json['results'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
status = json['status'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['message'] = this.message;
data['results'] = this.results.map((v) => v.toJson()).toList();
data['status'] = this.status;
return data;
}
}
class Results {
String? address1;
String? address2;
String? address3;
String? kana1;
String? kana2;
String? kana3;
String? prefcode;
String? zipcode;
Results(
{required this.address1,
required this.address2,
required this.address3,
required this.kana1,
required this.kana2,
required this.kana3,
required this.prefcode,
required this.zipcode});
Results.fromJson(Map<String, dynamic> json) {
address1 = json['address1'];
address2 = json['address2'];
address3 = json['address3'];
kana1 = json['kana1'];
kana2 = json['kana2'];
kana3 = json['kana3'];
prefcode = json['prefcode'];
zipcode = json['zipcode'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['address1'] = this.address1;
data['address2'] = this.address2;
data['address3'] = this.address3;
data['kana1'] = this.kana1;
data['kana2'] = this.kana2;
data['kana3'] = this.kana3;
data['prefcode'] = this.prefcode;
data['zipcode'] = this.zipcode;
return data;
}
}
APIからのJSONデータ取得
models/logic.dartにAPIからJSONデータを取得するコードを実装します。http.Responseを使って指定したURLからJSONデータを取得し、JSON to Dartで作成したAutogeneratedクラスのfromJson()で構造体に変換します。
strtmp変数はchangeNotifyしたあとUIから読み出すための変数です。 取り出した値の一部を格納します。
void requestSample() async {
var uri =
Uri.parse('https://zipcloud.ibsnet.co.jp/api/search?zipcode=0791100');
http.Response res = await http.get(uri);
if (res.statusCode == 200) {
String data = res.body;
Map<String, dynamic> map = jsonDecode(data);
var human = Autogenerated.fromJson(map);
// String address1 = map['results'][0]['address1'];
strtmp = human.results[0].address1!;
print(human.results[0].address1);
} else {
throw Exception('Failed to load post');
}
}
UIの実装
view/ui.dartでは、UI用のStatelessWidgetを作成し、取得したデータを表示するTextウィジェットを実装します。
前回記事と同様にUI用のStatelessWidgetを作っていきます。 中身はTextで先程詰め込んだstrtmpの値が更新されたら描画しています。
class PostcodeAddress extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
/// context からModelの値が使える
'${Provider.of<CountModel>(context).strtmp}',
style: Theme.of(context).textTheme.headline4,
);
}
}
全部コードを置いていく
正直上に書いたコードとimportだけで十分ですが、 前回の書いた記事のコードをベースに分離しているのでそのままです。
Provider Patternを使い、FlutterアプリUIとロジックを分離するための考察
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:mvvm_hotpepper/json/JsonStruct.dart';
class CountModel extends ChangeNotifier {
/// 初期値
int count = 0;
String address = "ウマ娘";
String res = "";
String strtmp = "";
/// count の更新メソッド
void increment() {
count++;
changeText();
requestSample();
notifyListeners();
}
void changeText() {
if (count > 5) {
address = "ウマ娘プリティーダービー";
}
}
void requestSample() async {
var uri =
Uri.parse('https://zipcloud.ibsnet.co.jp/api/search?zipcode=0791100');
http.Response res = await http.get(uri);
if (res.statusCode == 200) {
String data = res.body;
Map<String, dynamic> map = jsonDecode(data);
var human = Autogenerated.fromJson(map);
// String address1 = map['results'][0]['address1'];
strtmp = human.results[0].address1!;
print(human.results[0].address1);
} else {
throw Exception('Failed to load post');
}
}
}
ツールの実行結果
右下の虫眼鏡アイコンを叩くと結果のような値が取得できます。 今は、URLに郵便番号直打ちですがInputボックスなどと組み合わせれば郵便番号検索ができます。 ちなみに、画面描画の都合上虫眼鏡を2回クリックしないと住所が出ないですが…まぁ些細な話ですよ。
まとめ
この記事では、JSON to Dartを使ってFlutterアプリでJSONデータを取得し、Dartの構造体に変換する方法を説明しました。これを使えば、様々なAPIからデータを取得してFlutterアプリで利用できるようになります。また、UIとロジックが分離されているため、中規模のコードも作成できそうです。