Home > front end >  _TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type
_TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type

Time:07-22

I am trying to follow a tutorial on making a data model, implement a GET request and display my data. The api I am trying to hit starts with an object containing key value pairs. The tutorial api does not. I need to know how to do it the way I am trying as a lot of the api's I have encountered are structured that way. Here is the error I am getting.

enter image description here

Here is the code for my GET request:

import 'dart:convert';
import 'package:ffxiv_job_viewer/models/job_list_model.dart';
import 'package:ffxiv_job_viewer/utils/app_constants.dart';
import 'package:http/http.dart' as http;

class ApiService {
  Future<List<JobList>> getAllJobs() async {
    final allJobsUrl =
        Uri.parse(AppConstants.BASE_URL   AppConstants.JOB_LIST_URI);
    final response = await http.get(allJobsUrl);
    List<JobList> allJobs = [];
    List body = json.decode(response.body);
    body.forEach((job) {
      allJobs.add(JobList.fromJson(job));
    });
    print(response.statusCode);
    print(response.body);
    return allJobs;
  }
 }

Here is the code for my model file:

import 'dart:convert';

JobList jobListFromJson(String str) => JobList.fromJson(json.decode(str));

String jobListToJson(JobList data) => json.encode(data.toJson());

class JobList {
    JobList({
        required this.results,
    });

    List<Result> results;

    factory JobList.fromJson(Map<String, dynamic> json) => JobList(
        results: List<Result>.from(json["Results"].map((x) => Result.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "Results": List<dynamic>.from(results.map((x) => x.toJson())),
    };
}

class Result {
    Result({
        required this.id,
        required this.icon,
        required this.name,
        required this.url,
    });

    int id;
    String icon;
    String name;
    String url;

    factory Result.fromJson(Map<String, dynamic> json) => Result(
        id: json["ID"],
        icon: json["Icon"],
        name: json["Name"],
        url: json["Url"],
    );

    Map<String, dynamic> toJson() => {
        "ID": id,
        "Icon": icon,
        "Name": name,
        "Url": url,
    };
}

CodePudding user response:

json.decode() returns a Map<String, dynamic> instance not a List. The server you're sending the request to probably sends back a JSON which needs to be decoded into Map<String, dynamic> to be used in your mobile application.

Edit :

The URL you've provided returns this response :

{
"Pagination": {
    "Page": 1,
    "PageNext": null,
    "PagePrev": null,
    "PageTotal": 1,
    "Results": 40,
    "ResultsPerPage": 100,
    "ResultsTotal": 40
},
"Results": [
    {
        "ID": 1,
        "Icon": "/cj/1/gladiator.png",
        "Name": "gladiator",
        "Url": "/ClassJob/1"
    },
    {
        "ID": 2,
        "Icon": "/cj/1/pugilist.png",
        "Name": "pugilist",
        "Url": "/ClassJob/2"
    },
    {
        "ID": 3,
        "Icon": "/cj/1/marauder.png",
        "Name": "marauder",
        "Url": "/ClassJob/3"
    },
    {
        "ID": 4,
        "Icon": "/cj/1/lancer.png",
        "Name": "lancer",
        "Url": "/ClassJob/4"
    },
    {
        "ID": 5,
        "Icon": "/cj/1/archer.png",
        "Name": "archer",
        "Url": "/ClassJob/5"
    },
    {
        "ID": 6,
        "Icon": "/cj/1/conjurer.png",
        "Name": "conjurer",
        "Url": "/ClassJob/6"
    },
    {
        "ID": 7,
        "Icon": "/cj/1/thaumaturge.png",
        "Name": "thaumaturge",
        "Url": "/ClassJob/7"
    },
    {
        "ID": 8,
        "Icon": "/cj/1/carpenter.png",
        "Name": "carpenter",
        "Url": "/ClassJob/8"
    },
    {
        "ID": 9,
        "Icon": "/cj/1/blacksmith.png",
        "Name": "blacksmith",
        "Url": "/ClassJob/9"
    },
    {
        "ID": 10,
        "Icon": "/cj/1/armorer.png",
        "Name": "armorer",
        "Url": "/ClassJob/10"
    },
    {
        "ID": 11,
        "Icon": "/cj/1/goldsmith.png",
        "Name": "goldsmith",
        "Url": "/ClassJob/11"
    },
    {
        "ID": 12,
        "Icon": "/cj/1/leatherworker.png",
        "Name": "leatherworker",
        "Url": "/ClassJob/12"
    },
    {
        "ID": 13,
        "Icon": "/cj/1/weaver.png",
        "Name": "weaver",
        "Url": "/ClassJob/13"
    },
    {
        "ID": 14,
        "Icon": "/cj/1/alchemist.png",
        "Name": "alchemist",
        "Url": "/ClassJob/14"
    },
    {
        "ID": 15,
        "Icon": "/cj/1/culinarian.png",
        "Name": "culinarian",
        "Url": "/ClassJob/15"
    },
    {
        "ID": 16,
        "Icon": "/cj/1/miner.png",
        "Name": "miner",
        "Url": "/ClassJob/16"
    },
    {
        "ID": 17,
        "Icon": "/cj/1/botanist.png",
        "Name": "botanist",
        "Url": "/ClassJob/17"
    },
    {
        "ID": 18,
        "Icon": "/cj/1/fisher.png",
        "Name": "fisher",
        "Url": "/ClassJob/18"
    },
    {
        "ID": 19,
        "Icon": "/cj/1/paladin.png",
        "Name": "paladin",
        "Url": "/ClassJob/19"
    },
    {
        "ID": 20,
        "Icon": "/cj/1/monk.png",
        "Name": "monk",
        "Url": "/ClassJob/20"
    },
    {
        "ID": 21,
        "Icon": "/cj/1/warrior.png",
        "Name": "warrior",
        "Url": "/ClassJob/21"
    },
    {
        "ID": 22,
        "Icon": "/cj/1/dragoon.png",
        "Name": "dragoon",
        "Url": "/ClassJob/22"
    },
    {
        "ID": 23,
        "Icon": "/cj/1/bard.png",
        "Name": "bard",
        "Url": "/ClassJob/23"
    },
    {
        "ID": 24,
        "Icon": "/cj/1/whitemage.png",
        "Name": "white mage",
        "Url": "/ClassJob/24"
    },
    {
        "ID": 25,
        "Icon": "/cj/1/blackmage.png",
        "Name": "black mage",
        "Url": "/ClassJob/25"
    },
    {
        "ID": 26,
        "Icon": "/cj/1/arcanist.png",
        "Name": "arcanist",
        "Url": "/ClassJob/26"
    },
    {
        "ID": 27,
        "Icon": "/cj/1/summoner.png",
        "Name": "summoner",
        "Url": "/ClassJob/27"
    },
    {
        "ID": 28,
        "Icon": "/cj/1/scholar.png",
        "Name": "scholar",
        "Url": "/ClassJob/28"
    },
    {
        "ID": 29,
        "Icon": "/cj/1/rogue.png",
        "Name": "rogue",
        "Url": "/ClassJob/29"
    },
    {
        "ID": 30,
        "Icon": "/cj/1/ninja.png",
        "Name": "ninja",
        "Url": "/ClassJob/30"
    },
    {
        "ID": 31,
        "Icon": "/cj/1/machinist.png",
        "Name": "machinist",
        "Url": "/ClassJob/31"
    },
    {
        "ID": 32,
        "Icon": "/cj/1/darkknight.png",
        "Name": "dark knight",
        "Url": "/ClassJob/32"
    },
    {
        "ID": 33,
        "Icon": "/cj/1/astrologian.png",
        "Name": "astrologian",
        "Url": "/ClassJob/33"
    },
    {
        "ID": 34,
        "Icon": "/cj/1/samurai.png",
        "Name": "samurai",
        "Url": "/ClassJob/34"
    },
    {
        "ID": 35,
        "Icon": "/cj/1/redmage.png",
        "Name": "red mage",
        "Url": "/ClassJob/35"
    },
    {
        "ID": 36,
        "Icon": "/cj/1/bluemage.png",
        "Name": "blue mage",
        "Url": "/ClassJob/36"
    },
    {
        "ID": 37,
        "Icon": "/cj/1/gunbreaker.png",
        "Name": "gunbreaker",
        "Url": "/ClassJob/37"
    },
    {
        "ID": 38,
        "Icon": "/cj/1/dancer.png",
        "Name": "dancer",
        "Url": "/ClassJob/38"
    },
    {
        "ID": 39,
        "Icon": "/cj/1/reaper.png",
        "Name": "reaper",
        "Url": "/ClassJob/39"
    },
    {
        "ID": 40,
        "Icon": "/cj/1/sage.png",
        "Name": "sage",
        "Url": "/ClassJob/40"
    }
]
}

So the client should decode the response, and extract the data you need from the Results key

import 'dart:convert';
import 'package:ffxiv_job_viewer/models/job_list_model.dart';
import 'package:ffxiv_job_viewer/utils/app_constants.dart';
import 'package:http/http.dart' as http;

class ApiService {
  Future<List<JobList>> getAllJobs() async {
    final allJobsUrl =
        Uri.parse(AppConstants.BASE_URL   AppConstants.JOB_LIST_URI);
    final response = await http.get(allJobsUrl);
    List<JobList> allJobs = [];
    Map<String, dynamic> body = json.decode(response.body);
    body['Results'].forEach((job) {
      allJobs.add(JobList.fromJson(job));
    });
    print(response.statusCode);
    print(response.body);
    return allJobs;
  }
 }

CodePudding user response:

You cannot return jsonDecode() as Map<String, dynamic> inside a dynamic list. Try changing your dynamic list as List<Map<String, dynamic>>

import 'dart:convert';
import 'package:ffxiv_job_viewer/models/job_list_model.dart';
import 'package:ffxiv_job_viewer/utils/app_constants.dart';
import 'package:http/http.dart' as http;

class ApiService {
  Future<List<JobList>> getAllJobs() async {
    final allJobsUrl =
        Uri.parse(AppConstants.BASE_URL   AppConstants.JOB_LIST_URI);
    final response = await http.get(allJobsUrl);
    List<JobList> allJobs = [];
    Map<String, dynamic> body = json.decode(response.body); // Make a change here.
    body['Results'].forEach((job) {
      allJobs.add(JobList.fromJson(job));
    });
    print(response.statusCode);
    print(response.body);
    return allJobs;
  }
 }
  • Related