flutterdatetimedartbuilt-value

Flutter DateTime serializer with null safety


I'm using built_value in flutter, both libraries are null safe

built_value_generator: ^8.0.4
built_value: ^8.0.4

In my model I have a few DateTime objects they are all nullable. To serialize these I'm using a custom serializer that returns null if the string is null or empty. but it throws an exception

  Deserializing '[data, [{_id: 609e6ea910fd591efebd61a3, booking_id: 
  609e6ea99fe023fde50aa375,...' to 'BookingResponse' failed due to: Deserializing '[{_id: 
  609e6ea910fd591efebd61a3, booking_id: 609e6ea99fe023fde50aa375, client...' to 
  'BuiltList<Booking>' failed due to: Deserializing '[_id, 609e6ea910fd591efebd61a3, 
  booking_id, 609e6ea99fe023fde50aa375, client,...' to 'Booking' failed due to: type 'Null' 
  is not a subtype of type 'DateTime' in type cast
  

The exception happens when I deserialize an empty string to a DateTime declared in my model like this :

 DateTime? get booking_date;

using the serializer below (which will return null)

class DateTimeSerializer implements PrimitiveSerializer<DateTime?> {
  @override
  DateTime? deserialize(Serializers serializers, Object? serialized, {FullType specifiedType = FullType.unspecified}) {
   logger('DateTime.deserialize: $serialized');
    if (serialized != null && serialized is String && serialized.isNotEmpty) {
      logger('DateTime.deserialize parse: $serialized');
      return DateTime.parse(serialized).toLocal();
    } else {
      return null;
    }
  }

  @override
  Object serialize(Serializers serializers, DateTime? object, {FullType specifiedType = FullType.unspecified}) {
   logger('DateTime.serialize: $object');
    if (object != null) {
      return object.toUtc().toIso8601String();
    } else {
      return Object();
    }
  }

  @override
  Iterable<Type> get types => [DateTime];

  @override
  String get wireName => 'DateTime';
}

in my generated model I can see this :

     case 'booking_date':
      result.booking_date = serializers.deserialize(value,
          specifiedType: const FullType(DateTime)) as DateTime;
      break;

which suggests this can't be null, but then it also has this

DateTime? _booking_date;
DateTime? get booking_date => _$this._booking_date;
set booking_date(DateTime? booking_date) =>
  _$this._booking_date = booking_date;

which makes me think it can be, any idea why this would throw an exception?


Solution

  • I reported this as a bug in built_value_generator: https://github.com/google/built_value.dart/issues/1035

    Generated code has incorrect cast to DateTime, while it should have a cast to DateTime?.

    When changing cast to DateTime? in generated code - deserialization works fine.