json_serializable.dart icon indicating copy to clipboard operation
json_serializable.dart copied to clipboard

[WIP] Automatically convert custom Maps key types

Open TimWhiting opened this issue 3 years ago • 4 comments

Before

Map<int, String> // works
IMap<int, String> // does not work

Custom toJson / fromJson map types can now have keys serialized to strings. This expects the to/fromJson function to be of the form String Function(Object?) and Object? Function(String).

Resolves: #396

@kevmoo

TimWhiting avatar Oct 04 '21 21:10 TimWhiting

Addressed your comments.

The point of this PR is to allow custom implementations of from/toJson with generics to have key values automatically serialized to strings (such as ints, doubles, datetime, and enums). Keys were being serialized properly for built in map types, but not for custom maps such as the immutable map type I'm using from the fast_immutable_collections package. The approach I took was to reuse the key serialization logic that is used for regular maps in generic types that have String? types instead of the regular Object? type in the toJsonK/fromJsonK functions.

i.e.

class CustomMap<K, V> {
  final Map<K, V> map;

  CustomMap(this.map);

  factory CustomMap.fromJson(
    Map<String, dynamic> json,
    K Function(String?) fromJsonK,
    V Function(Object?) fromJsonV,
  ) =>
      CustomMap(json.map<K, V>(
          (key, value) => MapEntry(fromJsonK(key), fromJsonV(value))));

  Map<String?, dynamic> toJson(
          String? Function(K) toJsonK, Object? Function(V) toJsonV) =>
      map.map((key, value) => MapEntry(toJsonK(key), toJsonV(value)));
}

TimWhiting avatar Jan 29 '22 03:01 TimWhiting

@TimWhiting Would this make it possible to serialize Firebase Timestamps?

FXschwartz avatar Apr 13 '22 14:04 FXschwartz

@FXschwartz This PR is for custom container types with non-string keys into a string (with the same support as built in containers)

My understanding is that Firebase Timestamps are encoded as a json object.

{
  nanoseconds: 0,
  seconds: 1562524200
}

Are you asking for Firebase Timestamps as keys? If so, in order to be valid json you can serialize it to a string to make it a string key. Which is related but not what this PR is for. The current implementation only handles the same things that normal maps handle as keys (e.g. enums, int, DateTime, Uri).

If you had something else / more specific in mind maybe I can help you find the right issue for it.

TimWhiting avatar Apr 13 '22 18:04 TimWhiting

@TimWhiting Sorry for the delay in response! Yes, I'm talking about being able to define Firebase Timestamp as a key.

I was hoping your PR was at least a workaround to #1072 where if I'm using the Firestore ODM package, json_serializable can handle the parsing of a Firestore Timestamp.

Hopefully, that makes sense, and yes if you have any ideas that would be greatly helpful, but probably don't need to exist in this PR discussion.

FXschwartz avatar Apr 19 '22 22:04 FXschwartz

I'm going to close this out. Feel free to re-open if you'd like to keep cranking...

kevmoo avatar Oct 04 '22 02:10 kevmoo