jsonflutterbuilt-valuechopper

Why am I getting an error when trying to call a method with flutter chopper and built value?


I'm getting The below ERROR,I believe it's because of null safety, this means that no data has been received or getSignedInUser() method is incorrect or class BuiltValueConverter is the cause.

(I tested the token with Postman and retrieved the data)

E/flutter (21792): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: Unhandled error Null check operator used on a null value occurred in Instance of 'AuthBloc'. E/flutter (21792): #0
BuiltValueConverter._deserialize package:todo_list_app/…/auth/built_value_converter.dart:51 E/flutter (21792): #1 BuiltValueConverter._convertToCustomObject package:todo_list_app/…/auth/built_value_converter.dart:36 E/flutter (21792): #2 BuiltValueConverter.convertResponse package:todo_list_app/…/auth/built_value_converter.dart:25

I'm using chopper with built_value Pubs. i'm trying to convert the coming json to object. Example:

{ "userName": "Jack", "email": "jack2066@gmail.com", "userRole": "USER", "created_at": "2021-07-03T16:49:56.774Z", "updated_at": "2021-07-03T16:49:56.774Z" }

the below code where the error start also explained in this Tutorial Converters & Built Value Integration

import 'package:built_collection/built_collection.dart';
import 'package:chopper/chopper.dart';
import 'package:todo_list_app/infrastructure/remote/auth/models/serializers.dart';

class BuiltValueConverter extends JsonConverter {

  @override
  Request convertRequest(Request request) {
    return super.convertRequest(
      request.copyWith(
        body: serializers.serializeWith(
          serializers.serializerForType(request.body.runtimeType)!,
          request.body,
        ),
      ),
    );
  }

  @override
  Response<BodyType> convertResponse<BodyType, SingleItemType>(
    Response response,
  ) {
    final Response dynamicResponse = super.convertResponse(response);
    final BodyType customBody =
        _convertToCustomObject<SingleItemType>(dynamicResponse.body);//
    return dynamicResponse.copyWith<BodyType>(body: customBody);
  }


  dynamic _convertToCustomObject<SingleItemType>(dynamic element) {
    if (element is SingleItemType) return element;

    if (element is List)
      return _deserializeListOf<SingleItemType>(element);
    else
      return _deserialize<SingleItemType>(element);
  }

  BuiltList<SingleItemType> _deserializeListOf<SingleItemType>(
    List dynamicList,
  ) {
    // Make a BuiltList holding individual custom objects
    return BuiltList<SingleItemType>(
      dynamicList.map((element) => _deserialize<SingleItemType>(element)),
    );
  }

  SingleItemType _deserialize<SingleItemType>(Map<String, dynamic> value,) {
    // We have a type parameter for the BuiltValue type, which should be returned after deserialization.
    return serializers.deserializeWith(
      serializers.serializerForType(SingleItemType)!, // Error Start
      value,
    );
  }

}

Here is my Chopper service code, getSignedInUser throw the error. I don't know if the implementation of the getSignedInUser method is correct or not.

import 'package:chopper/chopper.dart';
import 'package:injectable/injectable.dart';
import 'package:todo_list_app/infrastructure/remote/auth/built_value_converter.dart';
import 'package:todo_list_app/infrastructure/remote/auth/models/auth_built_model.dart';
import 'package:todo_list_app/infrastructure/remote/core/constants.dart';

part 'auth_service.chopper.dart';

@singleton
@ChopperApi() 
abstract class AuthService extends ChopperService {
  @factoryMethod
  static AuthService create() {
    final client = ChopperClient(
      baseUrl: AUTH_BASE_URL_External,
      services: [
        _$AuthService(),
      ],
      converter: BuiltValueConverter(),
      errorConverter: JsonConverter(),
      interceptors: [
        HttpLoggingInterceptor()
      ],
    );
    return _$AuthService(client);
  }

  @Post(path: '/signup')
  Future<Response> signUp(@Body() RegisterRequestModel body);

  @Post(path: '/signin')
  Future<Response<LoginResponseModel>> singIn(@Body() LoginRequestModel body);

  //headers: {AUTH_HEADER:BEARER+'authValue'}
  @Get(path: '/auth', )//authValue='Bearer Token'
  Future<Response<UserResponseModel>> getSignedInUser(@Header("Authorization") String authValue);//error Unhandled error Null check operator used on a null value
}

Any idea how to solve this Error? also Is there a good documentation for Chopper or alternative pub with a good documentation? Thanks


Solution

  • I think you are missing values in your "serielizers.dart" file it should be as followed :

        @SerializersFor(const[RegisterRequestModel,LoginRequestModel,UserResponseModel])
    final Serializers serializers =
    (_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();