この記事は Flutter Advent Calendar 2018 - Qiita の20日目の記事です。
概要
FlutterにおけるJSONのデコード(エンコード)についてまとめます。
まとめ
小規模なプロジェクトでは手動デコードでもいいかもしれませんが、中規模以上のプロジェクトではコードジェネレーター(json_serializable)を使ったほうが良さそうです。
やり方
手動デコードの場合
Flutterはデフォルトで dart:convert
というパッケージが入っているので
JsonCodec class で簡単にシリアライズできます。
{
"name": "John Smith",
"email": "john@example.com"
}
Map<String, dynamic> user = json.decode(json);
print('Howdy, ${user['name']}!');
print('We sent the verification link to ${user['email']}.');
json.decode()
の戻り値の型は Map<String, dynamic>
なので実行するまでJSONのValueがどの型になるかは分かりません。
また、デコード処理するロジックにキー名を書かないといけません。そのままStringで書いているのでtypoする可能性があります。
モデルクラスを使う場合
User
というモデルクラスを用意し User.fromJson()
/ User.toJson()
を定義します。
class User {
final String name;
final String email;
User(this.name, this.email);
User.fromJson(Map<String, dynamic> json)
: name = json['name'],
email = json['email'];
Map<String, dynamic> toJson() =>
{
'name': name,
'email': email,
};
}
Map userMap = json.decode(json);
var user = new User.fromJson(userMap);
print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');
エンコード・デコードのロジックをモデルクラスに内包することができました。
呼び出し側ではname
とemail
をStringではなくUserクラスのフィールドを参照しているので、typoしていた場合はコンパイルエラーで気がつくことができます。
コードジェネレーターライブラリを使う場合
pubspec.yaml
にjson_annotation
とjson_serializable
を追加します。
dependencies:
json_annotation: ^2.0.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: ^2.0.0
User
クラスを定義してJsonSerializable
アノテーションを付与します。
import 'package:json_annotation/json_annotation.dart';
// ジェネレートされたクラスからUserクラスのprivateメンバ変数にアクセスするため
part 'user.g.dart';
@JsonSerializable()
class User {
User(this.name, this.email);
String name;
String email;
// _$UserFromJsonが生成される
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
// _$UserToJsonが生成される
Map<String, dynamic> toJson() => _$UserToJson(this);
}
FlutterプロジェクトのRootでコマンドラインで以下を実行。()
flutter packages pub run build_runner build
実行後、コードが生成されるので前述したやり方と同様にエンコードできます。
Map userMap = json.decode(json);
var user = User.fromJson(userMap);
エンコード・デコードのロジックをコードジェネレーターに移譲することで、'name'
と'email'
を書く必要がなくなりました。
補足
JSONのキーと別名でモデルクラスのメンバ変数を定義した場合(例えばキーがsnake_caseでメンバ変数名をlowerCaseにしたい場合)はJsonKey
アノテーションをつけることでJSONのキー名を指定できます。
@JsonKey(name: 'first_name')
final int firstName;
以下のコマンドをFlutterプロジェクトのRootで実行することで、変更を検知してコード生成を自動化することもできます。
flutter packages pub run build_runner watch