0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Flutter】Retrofit使用時のContent-Type:html/textの対応

Last updated at Posted at 2024-12-18

はじめに

APIレスポンスのHeaderのContent-Typeがtext/html形式で、レスポンス内容がJSON形式だったときにretrofit(JsonSerializable)の自動パースを適用したかった時の対処法のメモです。

retrofitではJsonSerializableと組み合わせることでパースしたクラスを返すFutureクラスを自動生成してくれます。

問題の状況

APIのレスポンスがJson形式のテキストなのにも関わらず、仕様によりContent-Typeがtext/htmlでした。

  • レスポンス
{
    data:{
        name : "hoge",
        age : 20
    }
}

Freezedを用いて上記のレスポンスに対するモデルおよびAPIサービスクラスを作成していたのですが、Content-Typeがjson/aplicationでなかったため、自動パースが行えませんでした。

  • モデル
@freezed
class UserModel with _$UserModel {
    const factory UserModel({
      required String name,
      required int age,
    }) = _UserModel;
    factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);
}
  • APIサービスクラス
@RestApi(baseUrl: 'http://...')
abstract class ApiService {
    factory ApiService(Dio dio) = _ApiService;

    @GET('/user')
    Future<UserModel> getUser();
}

解決方法

dioのinterceptorでJsonデコードを行う

InterceptorWrapperクラスにonResponseプロパティがあるので、そこでretrofitに渡されるレスポンスを変換します。
statusコードが200番の時にJsonDecodeを行い、handler.nextでResponseを渡します。

final apiServiceProvider = Provider((ref) {
  final dio = Dio();

  // content-typeをtext/htmlに設定
  dio.options.headers['Content-Type'] = 'text/html; charset=UTF-8';

  // text/html形式のレスポンスをjson形式に変換
  dio.interceptors.add(
    InterceptorsWrapper(
      onResponse: (response, handler) {
        if (response.statusCode == 200) {
          final data = response.data.toString();
          try {
            final jsonData = jsonDecode(data);
            handler.next(
              Response(
                data: jsonData,
                requestOptions: response.requestOptions,
                statusCode: response.statusCode,
                statusMessage: response.statusMessage,
                isRedirect: response.isRedirect,
                redirects: response.redirects,
                extra: response.extra,
                headers: response.headers,
              ),
            );
          } on Exception catch (_) {
            // エラーが発生した場合はそのまま返す
            handler.next(response);
          }
        }
      },
    ),
  );

  return apiService(dio);
});

終わりに

Json形式なのにtextという特殊な状況ですがこのような形で対処できました。

もっとスマートな方法あればコメント等お願いします!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?