クラスの値を簡単にデバック出力したいと感じたことはないですか?
toStringで、簡単に値を出力したいと感じたことはないですか?
そんな時に、dart:convertとjson_serializableを使うと楽ですよ、という話です。
もちろん、JSONのシリアライズとデシリアライズにも使えます。
dart:convertとは
dart:convertは、Base64やJSON、UTF8などを変換するクラスが入ったライブラリです。SDKとして標準パッケージに入っているので、依存関係の設定がなくても、使用できます。
json_serializableとは
json_serializableは、JSONのシリアライズとデシリアライズのコードを生成するライブラリです。
ただ、処理を見ると、モデルとMapの変換をやっているだけのようです。(dart:convertを使うことで、JSONとMapの相互変換ができるので、JSON処理をすることができます)
使い方は、モデルにアノテーションを追加して、コマンドを叩くと、相互変換するコードが生成されます。コードは、変換するだけの関数なので、モデルに関数を追加して使用できるようにすれば、出来上がりです。
コードを生成するためには、3つのパッケージを依存関係に追加する必要があります。
実装
では、実装していきましょう。
コンソール上で実行していくので、IDEを使っている方は、適宜読み替えてください。
- プロジェクト作成
- 依存関係の設定
- モデルクラスの作成
- アノテーションの追加とpartディレクティブの追加
- コード生成
- 生成されたコードの追加
プロジェクト作成
今回は、Stagehandパッケージを使って、プロジェクトを生成しています。
新規フォルダを作成して、stagehandでシンプルなコンソールアプリの雛形を作ります。
$ mkdir jsontest
$ cd jsontest
$ stagehand console-simple
依存関係の設定
pubspec.yamlに、依存関係を追加します。
開発時にコードを生成をするので、dev_dependenciesに、build_runnerとjson_serializableを追加します。
モデルには、アノテーションの設定を行います。シリアライズ、デシリアライズでアノテーションを使用するので、dependenciesに、json_annotationを追加します。
2020年3月10日時点での、最新は以下になります。
$ vi pubspec.yaml
dependencies:
json_annotation: ^3.0.1
dev_dependencies:
build_runner: ^1.8.0
json_serializable: ^3.2.5
依存関係があるパッケージをコマンドでインストールします。
$ pub get
モデルクラスの作成
$ vi bin/example.dart
次のコードをexample.dartにコピーしてください。
import 'package:json_annotation/json_annotation.dart';
part 'example.g.dart'; // コード生成ができていないのでここはエラー
@JsonSerializable(nullable: false)
class Person {
final String firstName;
final String lastName;
final DateTime dateOfBirth;
Person({this.firstName, this.lastName, this.dateOfBirth});
}
重要なのは、import、part、@JsonSerializableです。
part部分は、コード生成後にできるファイルなので、読み込みができなくて、エラーになっているはずです。
また、partのコードがないとコマンド実行で、コード生成がされません。
なお、作られるファイル名も決まっていて、example.dartだったら、example.g.dartのファイルが作成されます。
コード生成
次は、build_runnerによるコード生成です。pubは、パッケージ管理のコマンドです。
$ pub run build_runner build
生成されたコードの追加
クラスに、ファクトリーとtoJson関数を追加してみましょう。また、toStringも追加します。
マッピング自体は、example.g.dartに作成されているはずなので、example.dartでは、それを使います。
$ vi example.dart
import 'package:json_annotation/json_annotation.dart';
import 'dart:convert'; // ここを追加
part 'example.g.dart';
@JsonSerializable()
class Person {
final String firstName;
final String lastName;
final DateTime dateOfBirth;
Person({this.firstName, this.lastName, this.dateOfBirth});
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json); // ここを追加
Map<String, dynamic> toJson() => _$PersonToJson(this); // ここを追加
@override
String toString() => json.encode(toJson()); // ここを追加
}
使ってみよう
雛形で、main.dartが作成されているので、それを変更します。
クラスのインスタンスを作成して、toStringの呼び出しを行います。
問題なければ、JSONが出力されます。
$ vi bin/main.dart
import 'example.dart';
void main(List<String> arguments) {
var p = Person(firstName: 'firstName', lastName: 'lastName', dateOfBirth: DateTime.now());
print(p.toString());
}
{"firstName":"firstName","lastName":"lastName","dateOfBirth":"2020-03-11T17:26:27.204499"}
コメント