I have a problem with parsed JSON in Flutter-Dart. Actually, there is no problem, but there is a method which I don't know. I'm getting data from a PHP server and I'm writing to listview from parsed JSON. However, I don't want to write to a listview, I just want to get data from the parsed JSON because I will set an another textview from parsed json data which I get.
This is my code.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Photo>> fetchPhotos(http.Client client) async {
final response =
await client.get(Uri.parse('https://meshcurrent.online/get_20word.php'));
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parsePhotos, response.body);
}
// A function that converts a response body into a List<Photo>.
List<Photo> parsePhotos(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();
}
class Photo {
final String questId;
final String quest;
final String ans1;
final String ans2;
final String ans3;
final String ans4;
final String correctAns;
final String category;
const Photo({
required this.questId,
required this.quest,
required this.ans1,
required this.ans2,
required this.ans3,
required this.ans4,
required this.correctAns,
required this.category,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
questId: json['questId'] as String,
quest: json['quest'] as String,
ans1: json['ans1'] as String,
ans2: json['ans2'] as String,
ans3: json['ans3'] as String,
ans4: json['ans4'] as String,
correctAns: json['correctAns'] as String,
category: json['category'] as String,
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
const appTitle = 'Isolate Demo';
return const MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Column(children: [
Text("ronalddo"),
Text("mecsfsi"),
FutureBuilder<List<Photo>>(
future: fetchPhotos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(
child: Text('An error has occurred!'),
);
} else if (snapshot.hasData) {
return PhotosList(photos: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
]));
}
}
class PhotosList extends StatelessWidget {
const PhotosList({Key? key, required this.photos}) : super(key: key);
final List<Photo> photos;
#override
Widget build(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.all(20),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: photos.length,
itemBuilder: (context, index) {
return ListTile(
title: Row(
children: [
Text(photos[index].quest),
Text(photos[index].ans1),
],
),
);
});
}
}
I want to do get only first column and get only questId from this parsed JSON. And I will set a textview using Getx library. I know set a data with Getx library but I can't do it because I don't know get the data.
If you just want to get the first questId of the List, do
photos[0].questId;
Related
I'm new to Flutter and I'm trying to create an application with a ListView using this API: https://metmuseum.github.io/#search. Here is my code:
main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'user.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MET',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<List<User>> usersFuture = getUsers();
static Future<List<User>> getUsers() async {
var body;
for (int i = 0; i < 5; i++) {
String url =
'https://collectionapi.metmuseum.org/public/collection/v1/objects/$i';
var response = await http.get(Uri.parse(url));
body = json.decode(response.body);
}
return body.map<User>(User.fromJson).toList();
}
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text("Metropolitan Museum of Art"),
centerTitle: true,
),
body: Center(
child: FutureBuilder<List<User>>(
future: usersFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
} /*else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
final users = snapshot.data!;
return buildUsers(users);
}*/
final users = snapshot.data!;
return buildUsers(users);
},
),
),
);
Widget buildUsers(List<User> users) => ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return Card(
child: ListTile(
leading: CircleAvatar(
radius: 28,
backgroundImage: NetworkImage(user.primaryImageSmall),
),
title: Text(user.title),
subtitle: Text(user.artistDisplayName),
),
);
},
);
}
user.dart
import 'package:flutter/material.dart';
class User {
final int objectID;
final bool isHighlight;
final String accessionYear;
final String primaryImage;
final String primaryImageSmall;
final String department;
final String objectName;
final String title;
final String culture;
final String period;
final String artistPrefix; //da usare prima dell'artista
final String artistDisplayName;
final String artistDisplayBio;
final String medium; //Refers to the materials that were used to create the artwork
final String dimensions;
final String geographyType; //da usare prima della città in cui è stata fatta l'opera
final String city;
final String state;
final String classification;
final String linkResource;
final String GalleryNumber;
const User(
{required this.objectID,
required this.isHighlight,
required this.accessionYear,
required this.primaryImage,
required this.primaryImageSmall,
required this.department,
required this.objectName,
required this.title,
required this.culture,
required this.period,
required this.artistPrefix,
required this.artistDisplayName,
required this.artistDisplayBio,
required this.medium,
required this.dimensions,
required this.geographyType,
required this.city,
required this.state,
required this.classification,
required this.linkResource,
required this.GalleryNumber});
static User fromJson(json) => User(
objectID: json['objectID'],
isHighlight: json['isHighlight'],
accessionYear: json['accessionYear'],
primaryImage: json['primaryImage'],
primaryImageSmall: json['primaryImageSmall'],
department: json['department'],
objectName: json['objectName'],
title: json['title'],
culture: json['culture'],
period: json['period'],
artistPrefix: json['artistPrefix'],
artistDisplayName: json['artistDisplayName'],
artistDisplayBio: json['artistDisplayBio'],
medium: json['medium'],
dimensions: json['dimensions'],
geographyType: json['geographyType'],
city: json['city'],
state: json['state'],
classification: json['classification'],
linkResource: json['linkResource'],
GalleryNumber: json['GalleryNumber']);
}
Now I'm having problems because the ListView is not created and gives me errors. Could you check the code and make sure everything is right?
I think the problem comes from the getUsers() class, where I try to get the API data.
In your user.dart file, you need a fromJson method but
it takes a map<String,dynamic> instead of a json
static User fromJson(Map<String, dynamic> json) => User(
objectID: json['objectID'],
isHighlight: json['isHighlight'],
accessionYear: json['accessionYear'],
primaryImage: json['primaryImage'],
primaryImageSmall: json['primaryImageSmall'],
department: json['department'],
objectName: json['objectName'],
title: json['title'],
culture: json['culture'],
period: json['period'],
artistPrefix: json['artistPrefix'],
artistDisplayName: json['artistDisplayName'],
artistDisplayBio: json['artistDisplayBio'],
medium: json['medium'],
dimensions: json['dimensions'],
geographyType: json['geographyType'],
city: json['city'],
state: json['state'],
classification: json['classification'],
linkResource: json['linkResource'],
GalleryNumber: json['GalleryNumber']);
}
And in your main file
You can create your instance of user like this :
static Future<List<User>> getUsers() async {
var body;
List<User> usersList = [];
for (int i = 1; i < 5; i++) {
String url =
'https://collectionapi.metmuseum.org/public/collection/v1/objects/$i';
var response = await http.get(Uri.parse(url));
body = json.decode(response.body);
usersList.add(User.fromJson(body));
}
return usersList;
}
and finally uncomment your code in the build method
I want to use the SWAPI API in my flutter project but the snapshot has no data (it's null). No key is needed and when I click on the website I get the json data.
I did everything like in this documentation https://docs.flutter.dev/cookbook/networking/background-parsing.
persons_page.dart:
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:star_wars/models/persons.dart';
class PersonsPage extends StatefulWidget {
const PersonsPage({ Key? key }) : super(key: key);
#override
State<PersonsPage> createState() => _PersonsPageState();
}
class _PersonsPageState extends State<PersonsPage> {
Future<List<Persons>> fetchPersons(http.Client client) async {
final response = await client.get(Uri.parse('https://swapi.dev/api/people/1'));
return compute(parsePersons, response.body);
}
List<Persons> parsePersons(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String,dynamic>>();
return parsed.map<Persons>((json) => Persons.fromJson(json)).toList();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Persons>>(
future: fetchPersons(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
print(snapshot.data);
return const Center(
child: Text("An error has occurred!"),
);
} else if (snapshot.hasData) {
return PersonsList(persons: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}
class PersonsList extends StatelessWidget {
const PersonsList({ Key? key, required this.persons }) : super(key: key);
final List<Persons> persons;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: persons.length,
itemBuilder: (context, index) {
return Text("Got it");
},
);
}
}
persons.dart:
class Persons {
final String name;
final String height;
final String mass;
final String hairColor;
final String skinColor;
final String eyeColor;
final String birthYear;
final String gender;
final List films;
final List vehicles;
final List starships;
const Persons({
required this.name,
required this.height,
required this.mass,
required this.hairColor,
required this.skinColor,
required this.eyeColor,
required this.birthYear,
required this.gender,
required this.films,
required this.vehicles,
required this.starships,
});
factory Persons.fromJson(Map<String, dynamic> json) {
return Persons(
name: json['name'] as String,
height: json['height'] as String,
mass: json['mass'] as String,
hairColor: json['hair_color'] as String,
skinColor: json['skin_color'] as String,
eyeColor: json['eye_color'] as String,
birthYear: json['birth_year'] as String,
gender: json['gender'] as String,
films: json['films'] as List,
vehicles: json['vehicles'] as List,
starships: json['starships'] as List,
);
}
}
the console output is:
Reloaded 1 of 632 libraries in 474ms.
I/flutter ( 6328): null
i don't know what is wrong with the code :/
I am trying o get data from coinmarketcap api but i seem to be getting the error above. included is my main.dart code, this is my first time using flutter/dart, so i don't quite understand everything, i followed this guide from flutter docs https://docs.flutter.dev/cookbook/networking/background-parsing , but i still got some errors that i then tried to solve by following this NoSuchMethodError: Class'_InternalLinkedHashMap<String, dynamic>'has no instance method 'cast' with matching arguments
Can anyone help me?
The error i get is this on line 22:
NoSuchMethodError (NoSuchMethodError: Class 'CastMap<String, dynamic, String, dynamic>' has no instance method 'call'.
Receiver: Instance of 'CastMap<String, dynamic, String, dynamic>'
My dart file:
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Criptos>> fetchcriptos(http.Client client) async {
final response = await client.get(
Uri.parse(
'https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest?id=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15'),
headers: {
"X-CMC_PRO_API_KEY": "ecfc8e0a-fd11-422d-8a7b-114e8b31e62c",
"Accept": "application/json"
});
return compute(parsecriptos, response.body);
}
List<Criptos> parsecriptos(String responseBody) {
final parsed = jsonDecode(responseBody).cast<String, dynamic>();
return parsed<Criptos>((json) => Criptos.fromJson(json)).toList();
}
class Criptos {
final int id;
final String name;
final String symbol;
final int max_supply;
final int cmc_rank;
final int preco;
const Criptos({
required this.id,
required this.name,
required this.symbol,
required this.max_supply,
required this.cmc_rank,
required this.preco,
});
factory Criptos.fromJson(Map<String, dynamic> json) {
return Criptos(
id: json['data']['id'] as int,
name: json['data']['name'] as String,
symbol: json['data']['symbol'] as String,
max_supply: json['data']['max_supply'] as int,
cmc_rank: json['data']['cmc_rank'] as int,
preco: json['data']['quote']['USD']['price'] as int);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
const appTitle = 'Isolate Demo';
return const MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Criptos>>(
future: fetchcriptos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(
child: Text('An error has occurred!'),
);
} else if (snapshot.hasData) {
return ListaCriptos(cripto: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
class ListaCriptos extends StatelessWidget {
const ListaCriptos({Key? key, required this.cripto}) : super(key: key);
final List<Criptos> cripto;
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: cripto.length,
itemBuilder: (context, index) {
return Text(cripto[index].id);
},
);
}
}
Github of the project
So I'm trying to build a list (of any kind) from a Json list object in flutter, I'm getting it using REST api the response is a Json list with the fields: type, contact {first_name, last_name}, created_at, uuid.
using this code I'm fetching the data and parsing it to custom data type
import 'dart:convert';
import 'package:connectix/models/calls.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
class ContactService {
static String _url = "https://api.voipappz.io/tasks//connectix_conversations_recent";
static Future browse() async{
var channel = IOWebSocketChannel.connect(Uri.parse(_url));
}
}
List<CallType> parseCalls(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<CallType>((json) => CallType.fromJson(json)).toList();
}
Future<List<CallType>> fetchCalls(http.Client client) async {
final response = await client
.get(Uri.parse("https://api.voipappz.io/tasks//connectix_conversations_recent"));
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parseCalls, response.body);
}
That's the data type model
class CallType {
final String type;
final String first_name, last_name;
final String created;
CallType({
required this.type,
required this.first_name,
required this.last_name,
required this.created,
});
factory CallType.fromJson(Map<String, dynamic> json){
return CallType(
type: json['type'],
first_name: json['contact.first_name'],
last_name: json['contact.last_name'],
created: json['created_at'],
);
}
}
and this is the code for the widget I'm trying to display and returns me the error in the question title
class CallsList extends StatelessWidget {
final List<CallType> calls;
CallsList({Key? key, required this.calls}) : super(key: key);
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: calls.length,
itemBuilder: (context, index) {
return Text(calls[index].type);
},
);
}
}
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.orange,
appBar: AppBar(
title: Text('hello'),
),
body: FutureBuilder<List<CallType>>(
future: fetchCalls(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? CallsList(calls: snapshot.data!)
: Center(child: CircularProgressIndicator());
},
),
);
}
}
You marked all attributes of CallType as required. It looks like the API is not returning data for one (or more) of these attributes.
You need either to mark them as optional (remove required and make them of type String?), or take care that your API is always responding with data.
I'm a very beginner at Flutter development, in the code below I tried to get data from here and display it in ListView :
static final String URL = "https://corona.lmao.ninja/countries";
Future<List<CoronaModel>> getData() async {
var data = await http.get(URL);
var jsonData = json.decode(data.body);
print("the count is: " + jsonData.toString()); //Data successfully printed
List<CoronaModel> listCoronaCountries = [];
for (var item in jsonData) {
CoronaModel mCorona = CoronaModel(
item["country"],
item["recovered"],
item["cases"],
item["critical"],
item["deaths"],
item["todayCases"],
item["todayDeaths"]);
listCoronaCountries.add(mCorona);
}
if (listCoronaCountries.length > 0) {
print("the count is: " + listCoronaCountries.length.toString());
} else {
print("EMPTY");
}
return listCoronaCountries;
}
At run time, the first print works, I can see the data successfully printed, but the IF statement is not showing
if (listCoronaCountries.length > 0) {
print("the count is: " + listCoronaCountries.length.toString());
} else {
print("EMPTY");
}
Model :
class CoronaModel {
final String country;
final String recovered;
final String cases;
final String critical;
final String deaths;
final String todayCases;
final String todayDeaths;
CoronaModel(this.country, this.recovered, this.cases, this.critical,
this.deaths, this.todayCases, this.todayDeaths);
}
You can copy paste run full code below
You can parse with coronaModelFromJson and display with FutureBuilder
code snippet
List<CoronaModel> coronaModelFromJson(String str) => List<CoronaModel>.from(
json.decode(str).map((x) => CoronaModel.fromJson(x)));
Future<List<CoronaModel>> getData() async {
var data = await http.get(URL);
List<CoronaModel> listCoronaCountries = coronaModelFromJson(data.body);
return listCoronaCountries;
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// To parse this JSON data, do
//
// final coronaModel = coronaModelFromJson(jsonString);
import 'dart:convert';
List<CoronaModel> coronaModelFromJson(String str) => List<CoronaModel>.from(
json.decode(str).map((x) => CoronaModel.fromJson(x)));
String coronaModelToJson(List<CoronaModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class CoronaModel {
String country;
int cases;
int todayCases;
int deaths;
int todayDeaths;
int recovered;
int active;
int critical;
int casesPerOneMillion;
CoronaModel({
this.country,
this.cases,
this.todayCases,
this.deaths,
this.todayDeaths,
this.recovered,
this.active,
this.critical,
this.casesPerOneMillion,
});
factory CoronaModel.fromJson(Map<String, dynamic> json) => CoronaModel(
country: json["country"],
cases: json["cases"],
todayCases: json["todayCases"],
deaths: json["deaths"],
todayDeaths: json["todayDeaths"],
recovered: json["recovered"],
active: json["active"],
critical: json["critical"],
casesPerOneMillion: json["casesPerOneMillion"],
);
Map<String, dynamic> toJson() => {
"country": country,
"cases": cases,
"todayCases": todayCases,
"deaths": deaths,
"todayDeaths": todayDeaths,
"recovered": recovered,
"active": active,
"critical": critical,
"casesPerOneMillion": casesPerOneMillion,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static final String URL = "https://corona.lmao.ninja/countries";
Future _future;
Future<List<CoronaModel>> getData() async {
var data = await http.get(URL);
List<CoronaModel> listCoronaCountries = coronaModelFromJson(data.body);
return listCoronaCountries;
}
#override
void initState() {
// TODO: implement initState
super.initState();
_future = getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FutureBuilder<List<CoronaModel>>(
future: _future,
builder: (BuildContext context,
AsyncSnapshot<List<CoronaModel>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Input a URL to start');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
' ${snapshot.data[index].country} , ${snapshot.data[index].cases}'),
);
});
}
}
}));
}
}
Instead of hand coding '.fromJson/.toJson' methods. you could rely on
this library https://github.com/k-paxian/dart-json-mapper,
It will help you not only for this case, but for all Dart Object => JSON => Dart Object cases.