Johan Walhout
Johan Walhout

Reputation: 1656

How create a interface (class) in Dart for an nested Map

In my Flutter app I receive notifications with a custom payload, like:

{ notification: 
  { 
    title: Test, 
    body: AAAA 
  }, 
  data: 
  { 
    productId: Axe, 
    page: Products, 
    click_action: FLUTTER_NOTIFICATION_CLICK
  }
}

Everything works well. I also can handle the payload of the notification by access it through: message['data']['page']

But I rather would like to use an Interface/Class to name the data by key, for example: message.data.page and message.data.productId

So I tried:

class NotificationMessage {
  Map notification;
  Map data;

  NotificationMessage(this.notification, this.data);
}

...
NotificationMessage _message = message; // Assigning the payload to the final
...

This where I get stuck: here I got the error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'NotificationMessage'.

My class isn't finished yet, but how to continue? I' aware of json_serializable, but before any tooling, I would like to understand it fully.

Upvotes: 1

Views: 1673

Answers (2)

king mort
king mort

Reputation: 1473

Instance of the json object. this way you can use a map for any instance without modifying the class

{ "notification": 
  { 
    "title": "Test", 
    "body": "AAAA" 
  }, 
  "data": 
  { 
    "productId": "Axe", 
    "page": "Products", 
    "click_action": "FLUTTER_NOTIFICATION_CLICK"
  }
}

Class looks like;

class NotificationMessage {
NotificationMessage({
    this.notification,
    this.data,
});

final Notification notification;
final Data data;

factory NotificationMessage.fromJson(Map<String, dynamic> json) => NotificationMessage(
    notification: Notification.fromJson(json["notification"]),
    data: Data.fromJson(json["data"]),
);

Map<String, dynamic> toJson() => {
    "notification": notification.toJson(),
    "data": data.toJson(),
};
}

class Data {
Data({
    this.productId,
    this.page,
    this.clickAction,
});

final String productId;
final String page;
final String clickAction;

factory Data.fromJson(Map<String, dynamic> json) => Data(
    productId: json["productId"],
    page: json["page"],
    clickAction: json["click_action"],
);

Map<String, dynamic> toJson() => {
    "productId": productId,
    "page": page,
    "click_action": clickAction,
};
}

class Notification {
Notification({
    this.title,
    this.body,
});

final String title;
final String body;

factory Notification.fromJson(Map<String, dynamic> json) => Notification(
    title: json["title"],
    body: json["body"],
);

Map<String, dynamic> toJson() => {
    "title": title,
    "body": body,
};
}

A function to build as

Future<NotificationMessage> getNotf() {
      var parsedJson = json.decode(//your received object);
  return NotificationMessage.fromJson(parsedJson);

}

Now you can receive this in a builder such as

 _futureNotifications =Future<NotificationMessage>

   _futureNotifications = getNotf(); //this is a function and can be used after a gesture or initState
    FutureBuilder<NotificationMessage>(
            future: _futureNotifications,
            builder: (context, snapshot) {
               }

Upvotes: 0

Lapa Ny Aina Tanjona
Lapa Ny Aina Tanjona

Reputation: 1268

First, you need to build the two models for notification and data as follows

class DataMessage {
  final String productId;

  final String page;

  final String click_action;

  DataMessage(this.productId, this.page, this.click_action);

  factory DataMessage.fromJson(Map<dynamic, dynamic> json) {
    return DataMessage(
      json['productId'] as String,
      json['page'] as String,
      json['click_action'] as String,
    );
  }
} 

class NotificationMessage {
  final String title;

  final String body;

  NotificationMessage(this.title, this.body);
  factory NotificationMessage.fromJson(Map<dynamic, dynamic> json) {
    return NotificationMessage(
      json['title'] as String,
      json['body'] as String,
    );
  }
}

The factory method convert map types into model classes.

Then you have to build a model for the response message as follows

class Message {
  final NotificationMessage notification;
  final DataMessage data;

  Message(this.notification, this.data);
  factory Message.fromJson(Map<dynamic, dynamic> json) {
    final Map<dynamic, dynamic> mapNotification = json['notification'];
    final Map<dynamic, dynamic> mapData = json['data'];
    
    final dataModel = DataMessage.fromJson(mapData);
    final notificationModel = NotificationMessage.fromJson(mapNotification);
    
    return Message(
      notificationModel as NotificationMessage,
      dataModel as DataMessage,
    );
  }
}

Note that the factory method allows you to convert the maps for each model to a class model

So you can define your response as a class

Map<dynamic, dynamic> messageResponse = {
  'notification': {'title': 'Test', 'body': 'AAAA'},
  'data': {
    'productId': 'Axe',
    'page': 'Products',
    'click_action': 'FLUTTER_NOTIFICATION_CLICK'
  }
};

final Message message = Message.fromJson(messageResponse);
  print(message.data.productId);
  print(message.data.page);
  print(message.data.click_action);
  
  print(message.notification.title);
  print(message.notification.body);

Hope that can help you

Upvotes: 4

Related Questions