前回まででいろいろなパターンマッチングの方法を見てきました。今回はそれらを総合して、Jsonのコンバートに使用する方法を紹介します。
Person
クラスの定義
変換プロセスを理解するために、まずPerson
クラスの定義を見てみましょう。
class Person {
final String? company;
final String name;
Person({this.company, required this.name});
}
Person
クラスは、company
とname
の2つのプロパティを持ちます。company
はnull許容型であり、すべてのPerson
インスタンスが会社に所属しているわけではないことを示しています。name
は必須フィールドです。
JSONデータのクラスへの変換
以下のfromJson
関数は、JSON形式のデータを受け取り、Person
クラスのインスタンスを生成して返します。この関数では、パターンマッチングを用いて、入力されたJSONデータの構造をチェックしています。
Person fromJson(Map<String, dynamic> json) {
if (json case {'company': String company, 'name': String name}) {
return Person(company: company, name: name);
} else if (json case {'name': String name}) {
return Person(name: name);
}
throw Exception('Illegal json format');
}
このコードでは、まずJSONデータがcompany
とname
の両方をキーとして含むかどうかをチェックしています。もし両方が存在すれば、それらの値を使用してPerson
インスタンスを生成します。name
のみが存在する場合は、company
を省略してインスタンスを生成します。どちらのパターンにも当てはまらない場合は、例外を投げて不正なフォーマットを示します。
JSONデータに含まれないキーがあった場合マッチしません。そのため、キーがない場合は値をnullに設定する、という方法が使えません。
テストケース
final person1 = fromJson({'company': 'Toyota', 'name': 'Suzuki'});
expect(person1, isNotNull);
expect(person1.company, 'Toyota');
expect(person1.name, 'Suzuki');
final person2 = fromJson({'name': 'Suzuki'});
expect(person2, isNotNull);
expect(person2.company, isNull);
expect(person2.name, 'Suzuki');
final person3 = fromJson({'company': 'Toyota', 'name': 'Suzuki', 'test': 'test'});
expect(person3, isNotNull);
expect(() => fromJson({'company': 'Toyota'}), throwsA(isA<Exception>()));
これらのテストケースは、fromJson
関数が期待通りに動作することを検証します。特に、必要なフィールドが存在するかどうか、および不正なフォーマットのデータが与えられた場合に例外が投げられるかどうかをチェックしています。
まとめ
Dartにおけるパターンマッチングを利用したJSONデータからクラスへのコンバート方法は、型安全かつ効率的なデータ変換を可能にします。ただ普通にFreezedなど変換生成のツール使うのが普通とは思いますが、パターンマッチングをJSON変換に使用する例が非常に面白かったため、ブログ記事を作成しました。