google / built_collection.dart

Immutable Dart collections via the builder pattern.
https://pub.dev/packages/built_collection
BSD 3-Clause "New" or "Revised" License
275 stars 53 forks source link

Serializers spread across projects? #216

Closed jimmyff closed 3 years ago

jimmyff commented 4 years ago

Hey @davidmorgan, could you possibly give me a little guidance with my serializer problem: My main serializers.dart file is in a package called core (dart native), my flutter app imports all the classes & serializers from the core project.

I've just made a BlobSerializer so I can store Uint8List data in Firestore, however this requires me to import the package cloud_firestore_platform_interface so I can access the Blob interface, this package requires the flutter SDK so cannot imported by my core project.

I've created the new serializer in my app project, but I'm unsure how to load it. Can my app can add to the existing serializers?

One solution could be to move all the serializers to the app project out of core?

jimmyff commented 4 years ago

I've tried moving serializers.dart & serializers.g.dart file over to my flutter app project however I can't a rebuild using build_runner as I get The Flutter SDK is not available.

davidmorgan commented 4 years ago

This issue should be on built_value, not built_collection :) but never mind.

Yes, your app can add to the existing serializers, and that's the way to do it. See

https://pub.dev/documentation/built_value/latest/serializer/Serializers/toBuilder.html

and then

https://pub.dev/documentation/built_value/latest/serializer/SerializersBuilder/add.html

or

https://pub.dev/documentation/built_value/latest/serializer/SerializersBuilder/merge.html

:)

jimmyff commented 4 years ago

Ah perfect, thanks so much!

jimmyff commented 3 years ago

Hi @davidmorgan so sorry I've come back to this and having a little bit of difficulty getting it to work. I assume I'm missing something wrong as not sure how to link it all together.

I have a dart project called core this has all my built_value models in and my main serializers file.

Then in a flutter project I import core but I'm trying to append a serializer that has a dependency on a flutter package (which is why it cant be included in core), My flutter serializer file looks like so:


library management.serializers;

import 'package:built_value/serializer.dart';
import 'package:core/models.dart';
import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart';
import 'timestamp_serializer.dart';

part 'serializers.g.dart';

@SerializersFor(const [
  Timestamp // I don't think this is required
])
final Serializers serializers = (_$serializers.toBuilder()
      // ..add(GeoPointSerializer())
      ..addPlugin(TimestampSerializerPlugin()))
    .build();

If I just import this file in my flutter apps main.dart file the analyser tells me it's unreferenced. I think the models in my core project are just using the core's version of the serializers and not this one. I'm not sure how it's all supposed to link together without using something like a singleton?

Thanks

davidmorgan commented 3 years ago

Right, you'll need some central place where you combine the various serializers instances into one instance for the whole codebase. You can can use serializers.merge to combine them, but note that it doesn't merge plugins, so you'll have to re-add those.

jimmyff commented 3 years ago

Thanks so much for the quick reply David, I really appreciate it. I don't suppose you know of anywhere I can see an example of this done as I'm struggling to wrap my head around it!

If I'm understanding correctly then I need to call my serializers something like coreSerializers and flutterSerializers and then somewhere do something like:

final Serializers serializers = (_$serializers.toBuilder()
      ..merge(coreSerializers)
      ..merge(flutterSerializers))
      // add all plugins here
    .build();

Would I just import this file in the flutter project and it should work or do I need to use/reference it somewhere?

I'm unclear on how variables can interact across packages, I've only really used classes from other packages until now.

If my code above is correct is there a way to keep the cores serializers named serializers (perhaps make it none-final and just update it in the flutter project?) as all the cores models are expecting serializers to be available as I use methods like this in the classes:

  // in the conversation class
  Map<String, dynamic> toJsonMap() {
    return Map.of(serializers.serialize(this,
            specifiedType: const FullType(Conversation)))
        .cast<String, dynamic>();
  }
davidmorgan commented 3 years ago

You're welcome :)

The merging doesn't need to use codegen; you could do e.g. final Serializers serializers = (coreSerializers.toBuilder()..merge(flutterSerializers)).build().

Actually you probably have one top level variable called serializers in your core package, another in the flutter package, and you want a third which is the merged one. You can deal with this using 'import as'. Do 'import as core;', 'import as flutter', then you can write

final Serializers serializers = (core.serializers.toBuilder()
      ..merge(flutter.serializers)
      // add all plugins here
    .build();
jimmyff commented 3 years ago

great, that worked like a chram, thanks so much @davidmorgan!

Have a great weekend!