個人的にはテストで多用していることが多いです。Jackson
ライブラリのObjectMapper
最高ですね。
具体的にどのようなユースケースで使用しているかという点に関しては、一番最後に記載しています。
なお、Jackson
ライブラリを使用したObjectMapper
の記事は大量に検索できます。ですので、きり丸の使用するユースケースの説明が独自ポイントとなります。
環境
- Java
- 17
- org.springframework.boot
- 2.6.4
- (com.fasterxml.jackson.core)
- 2.13.1
- (commons-io)
- 2.6
ユースケース
- テスト時にファイルからインスタンスを生成する
- 巨大なインスタンスだと分かりづらいので、JSONで構造を把握したい
コード
ObjectMapper#readValue
を使用します。第1引数にJSONファイルに対するクラス、第2引数にマッピング先の型を設定します。
第1引数にはURL
, InputStream
, File
クラス等々を渡せるように複数のメソッドが用意されています。第2引数にはClass<T>
, TypeReference<T>
, JavaType
クラス等々を渡せます。
シンプルに使用
プロダクトコード
個人的には、テストクラス側での使いやすさを考慮したInputStream
を使用するメソッドをラップして用意しています。そのまま使用すると検査例外(IOException)が発生するので、ラップして実行時例外(RuntimeException)にするとテストで扱いやすくなります。
// JSONファイルからclazzにマッピングする <T> T fromJson(InputStream input, Class<T> clazz) { try { return objectMapper.readValue(input, clazz); } catch (Exception e) { throw new RuntimeException(e); } }
テストコード
テストクラス側は次のように使用します。Class#getResourceAsStream
を使用するとresources
ディレクトリ配下から指定すればよいので、便利です。
@Test public void test_02() { var input = getClass().getResourceAsStream("/kirimaru/human.json"); Human expect = Human.builder() .age(18) .name("kirimaru") .build(); Human actual = helper.fromJson(input, Human.class); assertThat(actual).isEqualTo(expect); }
JSONファイルの文字コードを考慮
プロダクトコード
JSONファイルの文字コードを考慮する場合、いったん文字列にする必要があります。commons-io
のIOUtils.toString
を使用して、文字コードを考慮してファイルを読み込みます。
ファイルを扱う際はPath
クラスだと、とても簡単になるので私はPath
クラスでラップしています。
<T> T fromJson(Path path, Class<T> clazz) { File file = path.toFile(); try (FileInputStream input = new FileInputStream(file)) { return objectMapper.readValue(IOUtils.toString(input, StandardCharsets.UTF_8), clazz); } catch (Exception e) { throw new RuntimeException(e); } }
テストコード
特に解説しません。
@Test public void test_03() { Path path = Paths.get("src", "test", "resources", "kirimaru", "human.json"); Human expect = Human.builder() .age(18) .name("kirimaru") .build(); Human actual = helper.fromJson(path, Human.class); assertThat(actual).isEqualTo(expect); }
ソースコード
- cucumber-sample/ToClassHelper.java at e71a5de2e3a99abf4f1f8aeb26d61ac39fb7b564 · hirotoKirimaru/cucumber-sample · GitHub
- cucumber-sample/ToClassHelperTests.java at 94bb32edfa0bac91a8d3b2aaeb87418169a9db4e · hirotoKirimaru/cucumber-sample · GitHub
終わりに
今回の代表的なユースケースとしては、複雑なドメインになりがちなユーザーのインスタンス作成です。携帯を購入する、というユースケースをユーザーのロールごとに考えると分かりやすくなるでしょう。
ロール | 説明 |
---|---|
利用者 | 実際にサービスを利用しているユーザー。子ども等々 |
契約者 | サービスを契約したユーザー。契約したパパ等々 |
支払者 | サービスに対して金銭を支払うユーザー。ママが支払う等 |
利用者が未成年の場合、保護者が必要です。利用者が外国籍の場合は日本籍より厳密な身分証明書を求められることもあるでしょう。支払者はクレジットカード、銀行引き落とし等々、お金を払う手段を用意していなければなりません。また、すべてのロールを同一人物が行うパターンもあります。
ユーザーのロールによっては必須なデータ、非必須なデータがあります。一からJavaで生成していると記載する項目が多く、設定した条件が分かりづらくなってしまうので、JSONとして確認すると分かりやすくできます。
なお、Rubyではテストセットアップに使用するFactoryBotが優秀ですので、JSONファイルにしない方がよいでしょう。Javaだとスマートにテストセットアップできなかったので、JSONファイルで扱っていました。
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。