How to regroup JSON to match data types in Flutter?

Viewed 930

The goal here is to group JSON data by date and convert it into object in Flutter.

API of service I'm using returns JSON in this format:

        {
            "id": 1,
            "name": "Article Name",
            "created_at": "2020-01-10T00:33:09.000000Z",
        },
        {
            "id": 2,
            "name": "Article Name",
            "created_at": "2020-01-10T00:33:09.000000Z",
        },

I need to convert it to following format:

  Map<String, List<Article>> ArticleHistory = {
    '04.08.2020': [
      Article(id: 16, name: 'Article Name'),
      Article(id: 15, name: 'Article Name'),
      Article(id: 14, name: 'Article Name'),
      Article(id: 13, name: 'Article Name'),
    ],
    '03.08.2020': [
      Article(id: 12, name: 'Article Name'),
      Article(id: 11, name: 'Article Name'),
      Article(id: 10, name: 'Article Name'),
      Article(id: 9, name: 'Article Name'),
    ],
    '02.08.2020': [
      Article(id: 8, name: 'Article Name'),
      Article(id: 7, name: 'Article Name'),
      Article(id: 6, name: 'Article Name'),
      Article(id: 5, name: 'Article Name'),
    ],
    '01.08.2020': [
      Article(id: 4, name: 'Article Name'),
      Article(id: 3, name: 'Article Name'),
      Article(id: 2, name: 'Article Name'),
      Article(id: 1, name: 'Article Name'),
    ],
  };        

How that can be achieved?

1 Answers

Let you have data in the following format:

List<Map<String, dynamic>> articlesListJson = [
  {
    "id": 1,
    "name": "Article 1",
    "created_at": "2020-08-01T00:30:00.000000Z",
  },
  {
    "id": 2,
    "name": "Article 2",
    "created_at": "2020-08-01T00:45:00.000000Z",
  },
  {
    "id": 3,
    "name": "Article 3",
    "created_at": "2020-08-02T00:00:00.000000Z",
  },
];

(If you have a json string instead, use jsonDecode function to parse it to Dart's List of Map's).

As you want to store dates as dd.mm.yyyy String, write a helper function for converting 2020-08-01T00:30:00.000000Z to 01.08.2020:

String extractDateString(String dateTimeString) {
  DateTime dateTime = DateTime.parse(dateTimeString);
  String day = dateTime.day.toString().padLeft(2, '0');
  String month = dateTime.month.toString().padLeft(2, '0');
  String year = dateTime.year.toString().padLeft(4, '0');
  return '$day.$month.$year';
}

Then you'll be able to group the list by date:

Map<String, List<Map<String, dynamic>>> articleGroupsJson = groupBy(
  articlesListJson,
  (a) => extractDateString(a['created_at']),
);
// {'01.08.2020': [{...}, {...}], '02.08.2020': [{...}]}

groupBy is from collection package. Depend on it or just copy-paste function source.

Now parse each Map<String, dynamic> to Article class:

class Article {
  int id;
  String name;
  
  Article({this.id, this.name});
}

in a standard way:

Article parseArticle(Map<String, dynamic> map) {
  return Article(
    id: map['id'],
    name: map['name'],
  );
}

Because the data is already groupped, instead of simply mapping the list you'll need to map groups, and for each group map its value (which is list)

Map<String, List<Article>> articleGroups = articleGroupsJson.map(
  (date, list) => MapEntry(
    date,
    list.map(parseArticle).toList(),
  ),
);

Now articleGroups has the structure you want

Related