I'm new to Flutter/Dart and struggling through some of the new things.

I have an API that returns a status code, a message and a JWT token when a user tries to login.

I have this defining my AuthenticationResponse in responses.dart:

@JsonSerializable()
class AuthenticationResponse {
  @JsonKey(name: "status")
  String? status;
  @JsonKey(name: "message")
  String? message;
  @JsonKey(name: "token")
  String? token;

  AuthenticationResponse(this.status, this.message, this.token);

  factory AuthenticationResponse.fromJson(Map<String, dynamic> json) =>
      _$AuthenticationResponseFromJson(json);

  Map<String, dynamic> toJson() => _$AuthenticationResponseToJson(this);
}

I get a responses.g.dart generated with this:

Map<String, dynamic> _$AuthenticationResponseToJson(
        AuthenticationResponse instance) =>
    <String, dynamic>{
      'status': instance.status,
      'message': instance.message,
      'token': instance.token,
    };

in my app_api.dart:

@POST("/rpc/login")
  Future<AuthenticationResponse> login(
    @Field("email") String email,
    @Field("pass") String password,
  );

and this generates app_api.g.dart:

class _AppServiceClient implements AppServiceClient {
  _AppServiceClient(this._dio, {this.baseUrl}) {
    baseUrl ??= 'http://192.168.100.194:3000';
  }

  final Dio _dio;

  String? baseUrl;

  @override
  Future<AuthenticationResponse> login(email, password) async {
    const _extra = <String, dynamic>{};
    final queryParameters = <String, dynamic>{};
    final _data = {'email': email, 'pass': password};
    final _result = await _dio.fetch<Map<String, dynamic>>(
        _setStreamType<AuthenticationResponse>(
            Options(method: 'POST', headers: <String, dynamic>{}, extra: _extra)
                .compose(_dio.options, '/rpc/login',
                    queryParameters: queryParameters, data: _data)
                .copyWith(baseUrl: baseUrl ?? _dio.options.baseUrl)));
    final value = AuthenticationResponse.fromJson(_result.data!);
    return value;
  }

  RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
    if (T != dynamic &&
        !(requestOptions.responseType == ResponseType.bytes ||
            requestOptions.responseType == ResponseType.stream)) {
      if (T == String) {
        requestOptions.responseType = ResponseType.plain;
      } else {
        requestOptions.responseType = ResponseType.json;
      }
    }
    return requestOptions;
  }
}

When I run my code and try to login, I get the correct response echoed out by Dio, but then the code crashes on:

    final _result = await _dio.fetch<Map<String, dynamic>>(
        _setStreamType<AuthenticationResponse>(
            Options(method: 'POST', headers: <String, dynamic>{}, extra: _extra)
                .compose(_dio.options, '/rpc/login',
                    queryParameters: queryParameters, data: _data)
                .copyWith(baseUrl: baseUrl ?? _dio.options.baseUrl)));

with the error:

DioError [DioErrorType.other]: type 'List' is not a subtype of type 'Map<String, dynamic>?' in type cast

I understand this is a type error, but have no idea where or how I am supposed to set the type in the above code (which I've been adapting from a udemy course).

Any help much appreciated.


Solution 1: Anas Altarazi

if you share the json response it will help but I think you need to change Map<String,dynamic> to List<Map<String,dynamic>>