I have been trying to map a json cms to a flutter object and have tried various ways, this way seems to be the best so far, i found it in the Official Flutter Documentation. I’m not sure whats causing it not to map but the errors are stemming from this line:
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
what’s causing it not to map and how can i fix it?
my code is:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class Exercise {
final String title;
final String body;
final String basecamplevel;
final String element;
late String? image;
late String? video;
Exercise(
{required this.title,
required this.body,
required this.basecamplevel,
required this.element,
this.image,
this.video});
factory Exercise.fromMap(Map<String, dynamic> json) {
return Exercise(
title: json['content']['title'] as String,
body: json['content']['body'] as String,
basecamplevel: json['content']['basecamplevel'] as String,
element: json['content']['element'] as String,
image: json['content']['image'] as String?,
video: json['content']['video'] as String?,
);
}
}
Future<List<Exercise>> fetchExercises(http.Client client) async {
final response = await client.get(Uri.parse(
'https://api.storyblok.com/v2/cdn/stories?content_type=exercise&token=ACCESS_TOKEN'));
return parseExercises(response.body);
}
List<Exercise> parseExercises(String responseBody) {
try {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Exercise>((json)).toList();
} catch (e) {
debugPrint(e.toString());
return [];
}
}
my json is from the storyblok cms and looks like this :
{"stories":[{"name":"Fitball Balance","created_at":"2023-03-28T13:04:37.844Z","published_at":"2023-03-28T21:12:40.851Z","id":283199256,"uuid":"26f10325-d258-437e-8c78-d58ec6522d76","content":{"_uid":"73b84d96-ccf8-4738-b051-4b32dc1502d9","body":"Kneeling on big fitball and balancing trying not to touch the ground. Focus on single spot of the ground to maintain focus and balance ","image":{"id":7704374,"alt":"","name":"","focus":"","title":"","filename":"https://a.storyblok.com/f/212385/3253x4260/046c342607/59c6ea4b-e540-43e5-ae5f-92cdf6b786d7.jpeg","copyright":"","fieldtype":"asset","is_external_url":false},"title":"Fitball Balance","video":{"id":null,"alt":null,"name":"","focus":null,"title":null,"filename":"","copyright":null,"fieldtype":"asset"},"element":"Balance","component":"exercise","basecamplevel":"Level 1"},"slug":"fitball-balance","full_slug":"exercises/fitball-balance","sort_by_date":null,"position":-10,"tag_list":[],"is_startpage":false,"parent_id":282598867,"meta_data":null,"group_id":"3d738fd6-f616-452d-8eb9-0a5be54d1c71","first_published_at":"2023-03-28T13:07:16.996Z","release_id":null,"lang":"default","path":null,"alternates":[],"default_full_slug":null,"translated_slugs":null},{"name":"Air Form","created_at":"2023-03-27T12:56:19.146Z","published_at":"2023-03-28T21:13:00.416Z","id":282600170,"uuid":"50b1c58c-78f9-49ba-b283-86458d8ee306","content":{"_uid":"76562cd7-08cc-4bc3-8fba-97b46cbe5fc2","body":"The fourth elemental form learned in Freeform. Steps to learn air form ect ect","image":{"id":7690205,"alt":"","name":"","focus":"","title":"","filename":"https://a.storyblok.com/f/212385/750x1624/7ad9935aca/3b9f2bfb-3dc3-48b7-9aff-25077d1f6620.png","copyright":"","fieldtype":"asset","is_external_url":false},"title":"Air Form","video":{"id":null,"alt":null,"name":"","focus":null,"title":null,"filename":"","copyright":null,"fieldtype":"asset"},"element":"Air","component":"exercise","basecamplevel":"level 4"},"slug":"air-form","full_slug":"exercises/air-form","sort_by_date":null,"position":0,"tag_list":[],"is_startpage":false,"parent_id":282598867,"meta_data":null,"group_id":"60fd3a0f-57cb-41eb-bcaa-53c0e216f540","first_published_at":"2023-03-27T13:00:54.592Z","release_id":null,"lang":"default","path":null,"alternates":[],"default_full_slug":null,"translated_slugs":null}],"cv":1680037980,"rels":[],"links":[]}
I have tried different methods of mapping the json code to my Exercise object but i can’t get any of them to display in the app.
When I run the code this is the output i get:
I/flutter (26561): NoSuchMethodError: Class '_Map<String, dynamic>' has no instance method 'cast' with matching arguments.
I/flutter (26561): Receiver: _Map len:4
I/flutter (26561): Tried calling: cast<Map<String, dynamic>>()
I/flutter (26561): Found: cast<Y0, Y1>() => Map<Y0, Y1>
I/flutter (26561): AsyncSnapshot<List<Exercise>>(ConnectionState.done, [], null, null)
3
Answers
You can use following code to parse the data
Also there will be showing a cast error after this. Because image and video are not in String format. They are objects. They also need to map as models if you wants to use those data
You have to use
as
to convert in Flutter. Like this:jsonDecode(jsonString) as Map<String, dynamic>
. If you use "Visual Studio Code" I recommend you download the "Dart Data Class Generator" extension. This extension can generate this json conversion quickly.Saw your json. I would say that
content
image
andvideo
should be classes for you to use as an attribute of yourExercise
class.Use this json to dart converter and see what the logic of this implementation would look like
You are trying to handle the
jsonDecode
‘s output asList
but actually returnsMap
, so you have to takestories
to manage the list of objects.