skip to Main Content

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


  1. You can use following code to parse the data

    return (parsed['stories'] as List).map((e) => Exercise.fromMap(e)).toList();
    

    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

    Login or Signup to reply.
  2. 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 and video should be classes for you to use as an attribute of your Exercise class.

    Use this json to dart converter and see what the logic of this implementation would look like

    Login or Signup to reply.
  3. You are trying to handle the jsonDecode‘s output as List but actually returns Map, so you have to take stories to manage the list of objects.

    List<Exercise> parseExercises(String responseBody) {
      try {
        final parsed = (jsonDecode(responseBody)['stories'] as List).cast<Map<String, dynamic>>();
        return parsed.map<Exercise>((json) => Exercise.fromJson(json)).toList();
      } catch (e) {
        debugPrint(e.toString());
        return [];
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search