google / built_value.dart

Immutable value types, enum classes, and serialization.
https://pub.dev/packages/built_value
BSD 3-Clause "New" or "Revised" License
861 stars 183 forks source link

Converting object to an encodable object failed #756

Closed jimmyff closed 4 years ago

jimmyff commented 4 years ago

Hey, I have an issue with one of my classes is giving the error 'Converting object to an encodable object failed' when I try to json.encode() or when I pass it to something like firestore.updateData(). I can't figure out why as its the same format as my other classes that do work fine. I've created this little test:

    test('json', () {
      final uuidValue = uuid.v1();
      final first = CloudPhoto((b) => b
        ..ref = uuidValue
        ..size = 1024);

      final second = serializers.serializeWith(CloudPhoto.serializer, first);
      print(second);
      expect(json.encode(first), second);
    });

which gives output:

CloudPhoto json:

{ref: 3a1037a0-0d44-11ea-9906-ab6dd71b025f, size: 1024}
ERROR: Converting object to an encodable object failed: Instance of '_$CloudPhoto'
dart:convert                             JsonCodec.encode
test/models/cloud_photo_test.dart 41:19  main.<fn>.<fn>

Here is the class and the serializers file:

cloud_photo.dart

library datingnode.models.cloud_photo;

import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';

import 'serializers.dart';
import '_models.dart';

part 'cloud_photo.g.dart';

abstract class CloudPhoto implements Built<CloudPhoto, CloudPhotoBuilder> {
  static Serializer<CloudPhoto> get serializer => _$cloudPhotoSerializer;

  /// ID (uuid.v1) for photo
  String get ref;

  // /// date user registered
  @nullable
  String get color;

  /// date user registered
  int get size;

  /// is the photo proven to look like the user
  @nullable
  DateTime get verified;

  /// date this was moderated
  @nullable
  DateTime get moderated;

  factory CloudPhoto([updates(CloudPhotoBuilder b)]) = _$CloudPhoto;
  CloudPhoto._();
  factory CloudPhoto.fromJsonMap(Map<String, dynamic> data) {
    return serializers.deserializeWith(CloudPhoto.serializer, data);
  }
  Map<String, dynamic> toJsonMap() {
    return Map.of(serializers.serialize(this,
            specifiedType: const FullType(CloudPhoto)))
        .cast<String, dynamic>();
  }
}

my serializers:

library serializers;

import 'package:core/core.dart';

import '_models.dart';

import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';

// if (dart.library.io) 'package:mobile/serializers/date_time_serializer.dart'
// if (dart.library.js) 'package:web/serializers/date_time_serializer.dart';

import 'serializers/date_time_serializer.dart';
import 'serializers/geo_point_seralizer.dart';

part 'serializers.g.dart';

@SerializersFor(const [
  // Generic types
  BuiltList,
  BuiltMap,

  // Data types
  GenderEnum,
  PronounEnum,
  GeoPoint,

  // Models
  Account,
  CloudPhoto,
  ProfileQueue,
  Profile,
  Inbox,
  Conversation,
  ChatMessage,
  SearchProfile,

  // Pub/Sub Messages
  AccountNewMessage,
  AccountDeletedMessage,
  AccountReplicatedMessage,
  ProfileUpdatedMessage,
  SearchResultsMessage,
  SearchResultsNeededMessage,
  SwipeMessage
])
final Serializers serializers = (_$serializers.toBuilder()
      ..addPlugin(new StandardJsonPlugin())
      ..addBuilderFactory(
          new FullType(
              BuiltMap, [new FullType(GenderEnum), new FullType(bool)]),
          () => new MapBuilder<GenderEnum, bool>())
    // ..addBuilderFactory(new FullType(BuiltList, [new FullType(CloudPhoto)]),
    //     () => new ListBuilder<CloudPhoto>())

    // ..addPlugin(new GeoPointSerializerPlugin())
    // ..addPlugin(new DateTimeSerializerPlugin())
    )
    .build();
davidmorgan commented 4 years ago

I think those other classes must have a method called toJson defined on them, which is what json.encode is looking for:

https://api.dartlang.org/stable/2.6.1/dart-convert/JsonCodec/encode.html