Json_serializable.dart: Support custom Iterator/List types

Created on 24 Jan 2020  Β·  12Comments  Β·  Source: google/json_serializable.dart

I'm looking at how it can be possible to support Iterators that are not supported by default in
json_serializable.

Examples are ObservableList from Mobx or BuiltList from built_collection.

I am able to implement a basic solution, however it requires a JsonConverter for every type you plan to use with those Lists.

One example here: https://mobx.pub/guides/json shows that it works, but that Converter only works for ObservableList<Todo>, not ObservableList<T>. (And of course T in this case is either a basic JSON type or has a toJson method).

Another example from my codebase using BuiltList.

class BuiltListConverterNote
    implements JsonConverter<BuiltList<Note>, List<Map<String, dynamic>>> {
  const BuiltListConverterNote();

  @override
  BuiltList<Note> fromJson(List<Map<String, dynamic>> json) =>
      BuiltList.of(json.map((x) => Note.fromJson(x)));

  @override
  List<Map<String, dynamic>> toJson(BuiltList<Note> list) =>
      list.map((x) => x.toJson()).toList();
}

@JsonSerializable()
class ServiceOrder {
  @BuiltListConverterNote()
  final BuiltList<Note> notes;
}

The above works, but again I need to create that JsonConverter for every type like Note I want to use.

I'm looking for something like the following.

final factories = <Type, Function>{
  Note: (Map<String, dynamic> json) => Note.fromJson(json)
};

T make<T>(Type type, Map<String, dynamic> x) {
  return factories[type](x);
}

class BuiltListConverter<T>
    implements JsonConverter<BuiltList<T>, List<Map<String, dynamic>>> {

  const BuiltListConverter();

  @override
  BuiltList<T> fromJson(List<Map<String, dynamic>> json) =>
      BuiltList.of(json.map((x) => make(T, x)));

  @override
  List<Map<String, dynamic>> toJson(BuiltList<T> list) =>
      list.map((x) => (x as dynamic).toJson()).toList();
}

@JsonSerializable()
class ServiceOrder {
  @BuiltListConverter()
  final BuiltList<Note> notes;
}

This currently doesn't work.

Error running JsonSerializableGenerator
Could not generate `fromJson` code for `notes`.
None of the provided `TypeHelper` instances support the defined type.
package:hx_tech_app/domain/models.dart:28:25
   β•·
28 β”‚   final BuiltList<Note> notes;
   β”‚                         ^^^^^
   β•΅

Is there a different way I should approach this? Perhaps a TypeHelper?

I have been looking online for documentation for adding TypeHelper but I can't find any anywhere and the example in this repo does not add TypeHelpers.

Most helpful comment

@MisterJimson If you still need this, I wrote a package that add a custom builder that supports BuiltList and BuiltSet.

https://github.com/knaeckeKami/immutable_json_list_serializer

If you like, check it out and report to me if you run into any issues!

All 12 comments

Custom TypeHelper is your only path here.

You're right, we don't have a lot of docs on how to set those up. You have
to create your own builder, which takes some work!

On Fri, Jan 24, 2020 at 9:19 AM Jason Rai notifications@github.com wrote:

I'm looking at how it can be possible to support Iterators that are not
supported by default in
json_serializable.

Examples are ObservableList from Mobx or BuiltList from built_collection.

I am able to implement a basic solution, however it requires a
JsonConverter for every type you plan to use with those Lists.

One example here: https://mobx.pub/guides/json shows that it works, but
that Converter only works for ObservableList, not ObservableList.
(And of course T in this case is either a basic JSON type or has a toJson
method).

Another example from my codebase using BuiltList.

class BuiltListConverterNote

implements JsonConverter<BuiltList<Note>, List<Map<String, dynamic>>> {

const BuiltListConverterNote();

@override

BuiltList fromJson(List> json) =>

  BuiltList.of(json.map((x) => Note.fromJson(x)));

@override

List> toJson(BuiltList list) =>

  list.map((x) => x.toJson()).toList();

}

@JsonSerializable()
class ServiceOrder {

@BuiltListConverterNote()

final BuiltList notes;

}

The above works, but again I need to create that JsonConverter for every
type like Note I want to use.

I'm looking for something like the following.

final factories = {

Note: (Map json) => Note.fromJson(json)

};

T make(Type type, Map x) {

return factoriestype;

}

class BuiltListConverter

implements JsonConverter<BuiltList<T>, List<Map<String, dynamic>>> {

const BuiltListConverter();

@override

BuiltList fromJson(List> json) =>

  BuiltList.of(json.map((x) => make(T, x)));

@override

List> toJson(BuiltList list) =>

  list.map((x) => (x as dynamic).toJson()).toList();

}

@JsonSerializable()
class ServiceOrder {

@BuiltListConverter()

final BuiltList notes;

}

This currently doesn't work.

Error running JsonSerializableGenerator

Could not generate fromJson code for notes.

None of the provided TypeHelper instances support the defined type.

package:hx_tech_app/domain/models.dart:28:25

β•·

28 β”‚ final BuiltList notes;

β”‚ ^^^^^

β•΅

Is there a different way I should approach this? Perhaps a TypeHelper?

I have been looking online for documentation for adding TypeHelper but I
can't find any anywhere and the example in this repo does not add
TypeHelpers.

β€”
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/dart-lang/json_serializable/issues/593?email_source=notifications&email_token=AAAEFCU7FTQVYBG43CT7P2DQ7MPKHA5CNFSM4KLJN3M2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4IISO7FA,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAAEFCWKGO4HXRVV7S4CHLDQ7MPKHANCNFSM4KLJN3MQ
.

Thanks for the confirmation @kevmoo. Glad I wasn't missing something obvious.

It does seem like a feature to allow users to support custom list types without a TypeHelper would be cool. I've updated the title of this issue to reflect.

Could you point us in a direction on how to implement a custom TypeHelper?
I'd like to use custom list classes so that my models behave like value types.

Could you point us in a direction on how to implement a custom TypeHelper?
I'd like to use custom list classes so that my models behave like value types.

We don't have docs here. I exposed these types as a courtesy for relatively advanced and highly motivated users.

I totally admit, this is missing from the package – it's just not a high priority work item for me. Sorry. πŸ€·β€β™‚

@MisterJimson If you still need this, I wrote a package that add a custom builder that supports BuiltList and BuiltSet.

https://github.com/knaeckeKami/immutable_json_list_serializer

If you like, check it out and report to me if you run into any issues!

@knaeckeKami wrote a cool new package which serializes MobX Observable collections, check it out
https://pub.dev/packages/json_serializable_mobx

Is it possible to (de)-serialize types that one does not own (e.g. from third-party libraries like BuiltList) with this approach? If yes, I could deprecate my packages.

Is it possible to (de)-serialize types that one does not own (e.g. from third-party libraries like BuiltList) with this approach? If yes, I could deprecate my packages.

Not yet. That's the NEXT thing I'm working on...

Great, thanks for the info!

Are there any news about this?

Is it possible to (de)-serialize types that one does not own (e.g. from third-party libraries like BuiltList) with this approach? If yes, I could deprecate my packages.

This will come AFTER null safety lands.

So no work here likely until next year...

Was this page helpful?
0 / 5 - 0 ratings