ニュースアプリを作成する際にjsonのparseが出来なくて、freezedでつまづいていた

## はじめに
・この記事のテンプレートを、ChatGPTを使用して作成してもらいましたわ。
「いやー執筆がだいぶ楽になりましたね」などと言うが、普段からなかなか記事を書くことはありませんでした。
しかしながら、最近「アウトプット大全」という本を読みまして、早速行動に移しました。

## アプリ概要
・News API (ref: https://newsapi.org/) から取得した米国のヘッドラインニュースを表示するアプリケーションです。

・app

https://play.google.com/store/apps/details?id=com.cygnu.news_api

・code

https://github.com/cygnu/news_api

## 使用した主なパッケージ
* dio: ^4.0.6
* flutter_hooks: ^0.18.5+1
* freezed: ^2.3.2
* hooks_riverpod: ^2.1.3

## つまづいていたポイント
・アプリをMMVMで作成するという幾つかの記事を参考にコーディングをしていました。
このMMVMにてつまづいていると思っていたのですが、問題はfreezedで書いたModelにありました。

例えば、以下のjson形式のデータをparseするというもの。

```json
{
  "status": "ok",
  "totalResults": 68,
  "articles": [
    {
      "source": {
        "id": "reuters",
        "name": "Reuters"
      },
      "author": null,
      "title": "Musk donated around $1.95 billion in Tesla shares last year - Reuters",
      "description": "",
      "url": "https://www.reuters.com/markets/us/musk-donated-around-195-billion-tesla-shares-last-year-2023-02-15/",
      "urlToImage": "",
      "publishedAt": "2023-02-15T10:30:00Z",
      "content": ""
    },
    {
      "source": {
        "id": null,
        "name": "CNBC"
      },
      "author": "Lora Kolodny, John Rosevear",
      "title": "Tesla commits to open 7,500 chargers in the U.S. to other electric vehicles by end of 2024 - CNBC",
      "description": "",
      "url": "https://www.cnbc.com/2023/02/15/tesla-commits-to-open-7500-chargers-in-the-us-to-other-evs.html",
      "urlToImage": "",
      "publishedAt": "2023-02-15T10:00:01Z",
      "content": ""
    }
  ]
}
```

・[変更前] api_client.dart

```dart
class ApiClient {
  Future<Map<String, dynamic>> getHeadlineNews(String country, String apiKey) async {
    // dioを使用
    final dio = Dio();
    const baseUrl = 'https://newsapi.org/v2/top-headlines';
    // 後からわかったことだが、responseをfinalで受け取ることが悪かった。
    final response = await dio.get('$baseUrl?country=$country&apiKey=$apiKey');

    if (response.statusCode == 200) {
      try {
	    // 困ったことにjson.decodeすると、printで出力できない。
        // status: 200でresponseしたデータは拾えているはず。ならば、受け取るデータの型が悪いと分かる
		// print(json.decode(response.data));
        return response.data;
      } catch (e) {
        throw e;
      }
    } else {
      throw ('Request failed with status: ${response.statusCode}');
    }
  }
}
```

・[変更後] api_client.dart

```dart
class ApiClient {
  Future<NewsRoot> getHeadlineNews(String country, String apiKey) async {
    final dio = Dio();
    const baseUrl = 'https://newsapi.org/v2/top-headlines';

    // responseされたデータをResponse型に入れる
    Response response =
        await dio.get('$baseUrl?country=$country&apiKey=$apiKey');

    if (response.statusCode == 200) {
      try {
        // responseされたデータをjson形式で読み取り、NewsRoot型にConvert
        NewsRoot data = NewsRoot.fromJson(response.data);
        return data;
      } catch (e) {
        throw e;
      }
    } else {
      throw ('Request failed with status: ${response.statusCode}');
    }
  }
}
```

api_client.dartファイルの変更前と、変更後で型の変更を行っているのだが、ここをずっとDebugしても、jsonのデコードに失敗する。
それもそのはず、その前の段階で、freezedを使用して、Modelを作成した部分に問題が。
freezedの公式ドキュメントに記載されていたが、freezedにて、ListsやMaps, Setsを使用する際には、以下のように```@Freezed(makeCollectionsUnmodifiable: false)```を追記しなければならなかった。結構な時間悩んでいたが、こうしただけで、json形式に変換できるとは。

```diff_dart:news_root.dart
part 'news_root.freezed.dart';
part 'news_root.g.dart';

+ @Freezed(makeCollectionsUnmodifiable: false)
abstract class NewsRoot with _$NewsRoot {
  const factory NewsRoot({
    String? status,
    int? totalResults,
    List<NewsArticle>? articles,
  }) = _NewsInfo;

  factory NewsRoot.fromJson(Map<String, Object?> json) =>
      _$NewsRootFromJson(json);
}
```

## 参考文献
https://pub.dev/packages/freezed

https://qiita.com/SUGYKEN/items/d0f65f27af21a90e8d4d