Freezed: == operator fail when an attribute is a collection

Created on 13 Feb 2020  Â·  13Comments  Â·  Source: rrousselGit/freezed

for collections need to implement DeepCollectionEquality.

enhancement

Most helpful comment

I will add support for it asap.
I'll go with package:collection and generate code that uses DeepCollectionEquality for all Iterables and unconstrained generics

All 13 comments

Can't we just use something like https://github.com/passsy/kt.dart ?

I spent some time yesterday looking at all the capabilities of freezed and if I lose any features if I would migrate from built_value to freezed.

Basically everything I need is covered (more or less), but this is the only point where freezed doesn't offer a good solution at the moment if I did not miss something.

So, I want my models to behave like value types, and I want to (de)serialize them.
Dart Collections don't implement == correctly, so I cannot use them.
Even if freezed would special-case dart collections and use DeepCollectionEquality, the lists would still be mutable, which could cause problems.

freezed could potentially either return a copy or a read-only view of dart collections, but this would mean more special casing, I'm not sure if this is the right way.

Now, we could just use immutable collections like kt.dart or built_collection. But these collections are not recognized by json_serializable, and adding support for classes that you don't own is pretty hard.

You'll just get an error like

Error running JsonSerializableGenerator
Could not generate `fromJson` code for `<your list variable>`.
None of the provided `TypeHelper` instances support the defined type.

built_value offers a powerful Serializer architecture, that can be customized relatively easily.

I'm not sure what the best way forward is. If json_serializable would support adding custom types that you don't own, it would be easier.

I'll do some research on how hard it would be to write a custom builder that supports the most used immutable collection types (I think kt.dart and built_collection), but even if we have that, users would probably need to write their own build.yaml file if they want to use it, which is not great either.

something like this might be possible?

@immutable
abstract class Model<T> with _$Model<T> {
  const factory Model(
    @KtListConverter() KtList<T> Items,
  ) = _Model<T>;

  factory Model.fromJson(Map<String, dynamic> json) =>
      _$ModelFromJson(json);
}

class KtListConverter<T> implements JsonConverter<T, Object> {
  const KtListConverter();

  @override
  KtList<T> fromJson(Object json) {
    return  KtList.from(json.map(map) => Data.fromJson(map)).toList());
  }

  @override
  Object toJson(KtList<T> object) {
    return object.map((data) => data.toJson()).toList();
  }
}

Can't we just use something like https://github.com/passsy/kt.dart ?

That doesn't work with string literals, which is kind of bad.

for collections need to implement DeepCollectionEquality.

That's a fair request.\
But we'd need an annotation package for this to work (which could re-export package:collection).

What about lists of lists though?

something like this might be possible?

package:collection/collection.dart offers DeepCollectionEquality, which works on everything not just KtList. That's much more reliable.

@smiLLe I don't think that it works on generic types, you would have to write a converter for each type separately.

And it would be nice to have serialization without having to add an annotation on each collection type (although that pain would be tolerable).

I will add support for it asap.
I'll go with package:collection and generate code that uses DeepCollectionEquality for all Iterables and unconstrained generics

Because it requires a peer dependency on package:collection, I think I'll add an annotation package and switch from @immutable to @freezed in the end.

Would that be a problem?

I really think is fair enough user your own annotation, it will causes a very easy to repair break changes.
and it will change de dart.meta for a freezed import, will it?

I actually prefer @freezed.
@immutable is used in other contexts, too, @freezed is more googleable.

Alright. I'll publish a new version that uses a custom annotation, then I'll work on that.

Personally I'll vote for anything _except_ freezed :wink:

Haha, it's too late already.
You'll need to set up a filter in your email account 😜

Was this page helpful?
0 / 5 - 0 ratings