【Dart】パターンマッチングを利用したJSONデータからクラスへのコンバート

  • 2024年2月24日
  • 2024年2月21日
  • Dart

前回まででいろいろなパターンマッチングの方法を見てきました。今回はそれらを総合して、Jsonのコンバートに使用する方法を紹介します。

https://flutter.salon/dart/pattern-matching-switch/

Personクラスの定義

変換プロセスを理解するために、まずPersonクラスの定義を見てみましょう。

class Person {
  final String? company;
  final String name;

  Person({this.company, required this.name});
}

Personクラスは、companynameの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データがcompanynameの両方をキーとして含むかどうかをチェックしています。もし両方が存在すれば、それらの値を使用して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変換に使用する例が非常に面白かったため、ブログ記事を作成しました。

参考