Reputation: 2056
I'm trying to make an app that retrieves data from this JSON list and parse this data to a listview
.
With my code below, the first record I expect to see is ID
, NAME
and PRICE
, but it appears that I can't retrieve the PRICE
, because it's an int
and I'm calling for a string
from the JSON list.
Also, 'PRICE' is an int just like 'ID', as sam mentioned below, but 'ID' is fetched just fine whereas 'PRICE' just says 'NULL' in the list view
I don't know how to fix this, and hope I can get the answer I'm looking for on this platform.
FirstPage.dart :
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
home: StarWarsData(),
));
}
class StarWarsData extends StatefulWidget {
@override
StarWarsState createState() => StarWarsState();
}
class StarWarsState extends State<StarWarsData> {
final String url = "https://api.coinmarketcap.com/v2/ticker/";
List data;
Future<String> getSWData() async {
var res = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var resBody = json.decode(res.body);
data = resBody["data"];
});
return "Success!";
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Cryp-Tick Crypto Exchange"),
centerTitle: true,
backgroundColor: Colors.black,
),
body: ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
return new Container(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Card(
child: Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: <Widget>[
Text("Id: "),
Text('${data[index]["id"]}',
style: TextStyle(
fontSize: 18.0, color: Colors.black87)),
],
)),
),
Card(
child: Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: <Widget>[
Text("Name: "),
Text('${data[index]["name"]}',
style: TextStyle(
fontSize: 18.0, color: Colors.red)),
],
)),
),
Card(
child: Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: <Widget>[
Text("Price: "),
Text('${data[index]["price"]}',
style: TextStyle(
fontSize: 18.0, color: Colors.black87)),
],
)),
),
],
),
),
);
},
),
);
}
@override
void initState() {
super.initState();
this.getSWData();
}
}
The error I receive in the Debug Console:
E/flutter (25480): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (25480): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List' where
E/flutter (25480): _InternalLinkedHashMap is from dart:collection
E/flutter (25480): String is from dart:core
E/flutter (25480): List is from dart:core
Upvotes: 0
Views: 6020
Reputation: 42363
I don't think the problem is what you think. You have your data typed as a List
:
List data;
And you're populating it like this:
data = resBody["data"];
The error says:
type
'_InternalLinkedHashMap<String, dynamic>'
is not a subtype of type'List'
This suggests that resBody["data"]` is a map and not a list, and if you look at the JSON in the URL you're pulling, it starts like this:
{
"data": {
"1": {
That data
object is not a list/array, it's a an object/map. You should change the type of your data
variable to Map<String, dynamic>
of convert the data to a List
before storing it in the variable.
Edit after some comments
I was able to make this work by adding .values.toList()
and stripping the JSON down to just the first two records:
However with all of the JSON from that url it seems to error. So, maybe something in the JSON is triggering a bug. Even more strangely, it seems to work fine in DartPad!
Upvotes: 4