skip to Main Content

I’m attempting to access a JSON response from a server so I can output the contents on the screen, but I keep getting the error message: Unhandled Exception: type ‘List’ is not a subtype of type ‘Map<String, dynamic>’ in type cast. I’m fairly new to Dart and Json as a whole so I’m not sure where to go to fix this.
Here’s the code I have written:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import './user_credentials_struct.dart';

class Credentials with ChangeNotifier {
  List<Accounts> _items = [];

  List<Accounts> get items {
    return [..._items];
  }

  Future<void> fetchAccounts() async {
    final selectAccountUrl =
        Uri.parse('https://cs.csub.edu/~tesscuro/database/selectAccounts.php');
    try {
      final response = await http.get(selectAccountUrl);
      final receivedData = json.decode(response.body) as Map<String, dynamic>;
      final List<Accounts> loadedData = [];
      receivedData.forEach((accountID, data) {
        loadedData.add(
          Accounts(
            id: accountID,
            siteUrl: data['url'],
            password: data['password'],
            userName: data['username'],
          ),
        );
      });
      _items = loadedData;
      notifyListeners();
    } catch (error) {
      rethrow;
    }
  }
}

And this is a sample of the JSON response I get:

[{"cID":1,"url":"www.google.com","username":"test","password":"password"},{"cID":1,"url":"www.youtube.com","username":"test1","password":"password1"}]

I’ve changed the parameter types from String to ints, and rewritten code with different examples found. I’ve also changed the Map types to try and make it work.

2

Answers


  1. Read the error

    type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
    in type cast

    json response is List you should use

     final receivedData = json.decode(response.body) as List<dynamic>;
    

    Then you can convert it to Accounts object like this:

     final loadedData = receivedData
          .map((json) => Accounts(
              id: json['id'],
              siteUrl: json['url'],
              password: json['password'],
              userName: json['username']))
          .toList();
    

    The better approach is to have fromJson , toJson converters as part of Account class then you can simply write:

    final loadedData = receivedData
         .map((e) => Account.fromJson( e as Map<String,dynamic>))
         .toList();
    
    Login or Signup to reply.
  2. Basically your response is returning a List instead of a Map in other words you can write json.decode(response.body) as List<dynamic>. My suggestion is that you can use https://app.quicktype.io/ for creating your models by utilizing the existing JSON. In your case the model looks like this

    class Accounts {
      Accounts({
        required this.cId,
        required this.url,
        required this.username,
        required this.password,
      });
    
      int cId;
      String url;
      String username;
      String password;
    
      factory Accounts.fromJson(Map<String, dynamic> json) => Accounts(
            cId: json["cID"],
            url: json["url"],
            username: json["username"],
            password: json["password"],
          );
    
      Map<String, dynamic> toJson() => {
            "cID": cId,
            "url": url,
            "username": username,
            "password": password,
          };
    }
    

    Now inside of your fetchAccounts function, your implementation will look like this

    Future<void> fetchAccounts() async {
        final selectAccountUrl = Uri.parse('https://cs.csub.edu/~tesscuro/database/selectAccounts.php');
        try {
          final response = await http.get(selectAccountUrl);
          final receivedData = json.decode(response.body);
          print(receivedData);
          final listOfData = List<Accounts>.from(receivedData.map((x) => Accounts.fromJson(x)));
          _items = listOfData;
          notifyListeners();
        } catch (error) {
          rethrow;
        }
      }
    

    Basically, it takes the response data and converts your data into list of accounts. I hope this solves your confusion.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search