k-paxian / dart-json-mapper

Serialize / Deserialize Dart Objects to / from JSON
https://pub.dev/packages/dart_json_mapper
Other
402 stars 33 forks source link

Serialize and Deserialize from and to Map<String, dynamic> #8

Closed HerrNiklasRaab closed 5 years ago

HerrNiklasRaab commented 5 years ago

Hey @k-paxian,

as I started developing my base class repository for Firestore, another issue came up. The type of document data in the Firestore for Flutter package is always of type Map<String, dynamic>. Because Firestore is the go-to for Flutter and Angular developer, additional serialization and deserialization methods who can handle a Map<String, dynamic> type, would be a huge benefit. I would suggest the following signature:

static Map<String, dynamic> JsonMapper.serializeToMap(Object model);
static T JsonMapper.deserializeFromMap<T>(Map<String, dynamic> map);

Here is a simplified example of how I would use this in my repository:

class Repository<TModel extends DataModel> {
  CollectionReference collectionReference;

  Repository(this.collectionReference);

  Future update(TModel model) async {
    Map<String, dynamic> map = JsonMapper.serializeToMap(model);
    await collectionReference.document(model.id).updateData(map);
  }

  Future<TModel> get(String id) async {
    var snapshot = await collectionReference.document(id).get();
    return JsonMapper.deserializeFromMap<TModel>(snapshot.data)..id = id;
  }
}

What do you think about this?

Niklas

k-paxian commented 5 years ago

Hey @HerrNiklasRaab

I think it's not a direct responsibility for this library. And I would like to keep it as damn simple as possible.

For your case it could be achieved with something like that:

class Repository<TModel extends DataModel> {
  CollectionReference collectionReference;

  Repository(this.collectionReference);

  Future update(TModel model) async {
    Map<String, dynamic> map = JsonMapper.deserialize(JsonMapper.serialize(model));
    await collectionReference.document(model.id).updateData(map);
  }

  Future<TModel> get(String id) async {
    var snapshot = await collectionReference.document(id).get();
    TModel result = JsonMapper.deserialize(JsonMapper.serialize(snapshot.data));
    result.id = id;
    return result;
  }
}

Please verify this approach with the latest mapper version, get back if it'll cost you an issues.

HerrNiklasRaab commented 5 years ago

Hi Alex,

I think we are completely on the same side. As far as I understand, the main motivation for you to start this project was to develop a JSON library that is easy to set up, easy to use, and easy to maintain, so you can focus on really programming the project. Please correct me if I am wrong.

JsonMapper.deserialize(JsonMapper.serialize(snapshot.data))

Here are my thoughts on your suggested approach:

For example json_serializable:

final json = JSON.decode('{ "firstname" : "John", "lastname" : "Doe", "company" : { "name": "Awesome Inc." } }');
Customer customer = new Customer.fromJson(map);

built_value:

    var map = serializers.serializeWith(serializer, model)
        as Map<String, dynamic>;

jaguar_serializer:

 User user = userSerializer.fromMap({
        'name': 'John',
        'age': 25
      });

What downside do you see on this exactly?

Have an awesome day,

Niklas

k-paxian commented 5 years ago

Hi @HerrNiklasRaab

Exactly! :) I have a little justification at https://github.com/k-paxian/dart-json-mapper/wiki/Why-does-it-exist%3F

Your arguments absolutely acceptable, so I could suggest following correction

static Map<String, dynamic> toMap(Object object);
static T fromMap<T>(Map<String, dynamic> map);

This might be more easy to read, grasp and use.

HerrNiklasRaab commented 5 years ago

Yes, you are right, toMap and fromMap are definitely better names.

k-paxian commented 5 years ago

OK, done. Please verify on your end.