I want to get json from api in flutter - json

class Phone{
int? id;
bool? is_new;
String? title;
String? subtitle;
String? picture;
bool? is_buy;
dynamic best_seller;
int? price_without_discount;
int? discount_price;
Phone({
this.id,
this.is_new,
this.title,
this.subtitle,
this.picture,
this.is_buy,
this.best_seller,
this.price_without_discount,
this.discount_price
});
factory Phone.fromJson(Map <String, dynamic> json) => Phone(
id: json[MyPhoneKeys.id],
is_new: json[MyPhoneKeys.is_new],
title: json[MyPhoneKeys.title],
subtitle: json[MyPhoneKeys.subtitle],
picture: json[MyPhoneKeys.picture],
is_buy: json[MyPhoneKeys.is_buy],
best_seller: json[MyPhoneKeys.best_seller],
price_without_discount: json[MyPhoneKeys.price_without_discount],
discount_price: json[MyPhoneKeys.discount_price]
);
}
(My screen to display the data)
class CarouselSliderData extends StatefulWidget{
const CarouselSliderData({super.key});
#override
State<CarouselSliderData> createState() => CarouselSliderDataState();
}
class CarouselSliderDataState extends State<CarouselSliderData> {
int? id;
bool? is_new;
String? title;
String? subtitle;
dynamic picture;
bool? is_buy;
dynamic best_seller;
int? price_without_discount;
int? discount_price;
late Future<dynamic> phoneSpec;
#override
void initState() {
phoneSpec = MyApiService().getDataMocky();
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<dynamic>(
future: phoneSpec,
builder: (context, snapshot) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(snapshot.data!.id),
Text(snapshot.data!.is_new),
Text(snapshot.data!.title),
Text(snapshot.data!.subtitle),
Text(snapshot.data!.picture),
Text(snapshot.data!.is_buy),
Text(snapshot.data!.best_seller),
Text(snapshot.data!.price_without_discount),
Text(snapshot.data!.discount_price),
],
);
}
);
}
Future<dynamic> getData() async{
return await MyApiService().getDataMocky().then((value) async{
if(value != null){
setState((){
id = value!.id!;
is_new = value!.is_new!;
title = value!.title!;
subtitle = value!.subtitle!;
picture = value!.picture!;
is_buy = value!.is_buy!;
best_seller = value!.best_seller!;
price_without_discount = value!.price_without_discount!;
discount_price = value!.discount_price!;
});
return value;
}
},
);/*.catchError((_){
throw Exception("Exception is caught");
});*/
}
}
(my service to get data)
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:my_work/apiService/model.dart';
class MyApiService{
Future<dynamic> getDataMocky() async {
final response = await http.get(
Uri.parse('https://run.mocky.io/v3/654bd15e-b121-49ba-a588-960956b15175')
);
if(response.statusCode == 200){
return Phone.fromJson(json.decode(response.body)[1]);
}
return Exception();
}
}
is my model right for this api json from this api.
I want to get data and display them in carousel Slider(i will add it) but get nulls. The Error is saying Null is not subtype of String and nullcheck is used on NULL value and i don't know why and where is my mistake. Thank you very much

Text widget doesnt accept nullable string.
Instead of using ! it would be better to check null first, or you can provide default value on null case. Format will be like
if(snapshot.data!=null) Text(snapshot.data.id),
Or
Text(snapshot.data?.id??"got null"),
Or use String format like bellow, it will show null on null case.
Text("${snapshot.data?.id}"),
I will recommend checking understanding-null-safety

Related

Flutter SWAPI snapshot data null

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 :/

flutter error runes isnt a fuction or method and cant be invoked

List posts=[];
Future getPost()async{
var url="https://jsonplaceholder.typicode.com/posts" ;
var http;
var response = await http.get(url);
var responsebody = jsonDecode(response.body) ;
return responsebody ;
// ignore: dead_code
setState(() {
posts.addAll(responsebody);
});
}
#override
void initState() {
getPost();
super.initState();
}
// ignore: dead_code
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:Text('Alex',style: TextStyle(color: Colors.cyanAccent),),
backgroundColor: Colors.black87,centerTitle: true,),
drawer: Drawer(),
body: posts == null || posts.isEmpty ? Center(child: CircularProgressIndicator(),) :
Center( child: ListView.builder(
itemCount : posts.length,
itemBuilder :(context,i){
return Text("${posts[i]['title']}");
}
,)
));
}}
Add this class
class MyClass {
final int userId;
final int id;
final String title;
final String body;
MyClass(
this.userId,
this.id,
this.title,
this.body);
factory MyClass.fromMap(Map<String, dynamic> json) {
return MyClass(
json['userId'],
json['id'],
json['title'],
json['body']);
}
}
then change getPost() method to :
import 'package:http/http.dart' as http;
Future getPost()async{
var url="https://jsonplaceholder.typicode.com/posts" ;
var response = await http.get(url);
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
setState(() {
posts = parsed
.map<MyClass>((json) => MyClass.fromMap(json))
.toList();
});
}
The problem is with SDK tools. Open command prompt and run:
git clean -xfd
Restart your computer and then run:
flutter upgrade

Android Studio data from API

Basically im using an API where i can take a numberplate and show information on a vehicle. I managed to get everything working but can't seem to figure out how to display all the information.
Future<Album> fetchAlbum() async {
final response = await http
.get(Uri.parse('https://v1.motorapi.dk/vehicles/CZ33849'),
headers: {"X-AUTH-TOKEN": "rfrzsucnc7eo3m5hcmq6ljdzda1lz793",
"Content-Type": "application/json",
"Accept": "application/json",
});
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return Album.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
//headers: {"X-AUTH-TOKEN": "rfrzsucnc7eo3m5hcmq6ljdzda1lz793"}
class Album {
final String? registration_number;
final String? status;
final String? type;
final String? use;
final String? first_registration;
final String? vin;
final int? doors;
final String? make;
final String? model;
final String? variant;
final String? model_type;
final String? color;
final String? chasis_type;
final int? engine_power;
final String? fuel_type;
final String? RegistreringssynToldsyn;
final String? date;
final String? result;
Album({
this.registration_number,
this.status,
this.type,
this.use,
this.first_registration,
this.vin,
this.doors,
this.make,
this.model,
this.variant,
this.model_type,
this.color,
this.chasis_type,
this.engine_power,
this.fuel_type,
this.RegistreringssynToldsyn,
this.date,
this.result,
});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
registration_number: json['registration_number'],
status: json['status'],
type: json['type'],
use: json['use'],
first_registration: json['first_registration'],
vin: json['vin'],
doors: json['doors'],
make: json['make'],
model: json['model'],
variant: json['variant'],
model_type: json['model_type'],
color: json['color'],
chasis_type: json['chasis_type'],
engine_power: json['engine_power'],
fuel_type: json['fuel_type'],
RegistreringssynToldsyn: json['RegistreringssynToldsyn'],
date: json['date'],
result: json['result'],
);
}
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
#override
void initState() {
super.initState();
futureAlbum = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("${snapshot.data!.use}");
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
),
);
}
}
When i edit this line: return Text("${snapshot.data!.use}");, i can replace use with other variables from Album class, but i can't seem to figure out how to display it all at once.
How you want to display? It is depend on your UI. If you want to put it all in a single Text widget, you can do like that
class User {
String name;
String address;
toString() {
return "name: " + name + ", address: " + address;
}
}
Or You can use Column/Row Widget to show per Text Widget.

why i got this error Error: Expected a value of type 'List<dynamic>', but got one of type '_JsonMap'

hi i am making food app that shows recipes form spoonacular api so i made a home screen that get the data and show it in a list view i tried thus
'https://api.spoonacular.com/food/products/search?query=pizza&apiKey=8fe91444f092411fa6011b71fd6e582d'
but when i run the app it says Error: Expected a value of type 'List', but got one of type '_JsonMap' and doesn't show any data
the home screen class
import 'package:flutter/material.dart';
import 'package:flutter_application_1/recipes.dart';
import 'dart:convert' as cnv;
import 'package:http/http.dart' as http;
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
_HomeScreen createState() => _HomeScreen();
}
class _HomeScreen extends State<HomeScreen> {
List<recipes>? modell;
#override
void initState() {
// TODO: implement initState
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Food recipe api'),
),
body: modell == null
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ExpansionTile(
title: Text(modell![index].type.toString()),
children: [
Text('modell![index].uri.toString()'),
Container(
child:
Image.network('https://picsum.photos/250?image=9'),
)
],
),
);
},
itemCount: modell!.length),
);
}
Future<void> getData() async {
http.Response res = await http.get(Uri.parse('https://api.spoonacular.com/food/products/search?query=pizza&apiKey=8fe91444f092411fa6011b71fd6e582d'));
print(res.body);
List<dynamic> body = cnv.jsonDecode(res.body);
modell = body.map((dynamic item) => recipes.fromJson(item)).toList();
setState(() {});
}
}
the recipes class i used json to dart website to make this class
class recipes {
String ? type;
List<Products> ? products;
int ? offset;
int ? number;
int ? totalProducts;
int ? processingTimeMs;
int ? expires;
bool ? isStale;
recipes(
{this.type,
this.products,
this.offset,
this.number,
this.totalProducts,
this.processingTimeMs,
this.expires,
this.isStale});
recipes.fromJson(Map<String, dynamic> json) {
type = json['type'];
if (json['products'] != null) {
products = <Products>[];
json['products'].forEach((v) {
products!.add(new Products.fromJson(v));
});
}
offset = json['offset'];
number = json['number'];
totalProducts = json['totalProducts'];
processingTimeMs = json['processingTimeMs'];
expires = json['expires'];
isStale = json['isStale'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['type'] = this.type;
if (this.products != null) {
data['products'] = this.products!.map((v) => v.toJson()).toList();
}
data['offset'] = this.offset;
data['number'] = this.number;
data['totalProducts'] = this.totalProducts;
data['processingTimeMs'] = this.processingTimeMs;
data['expires'] = this.expires;
data['isStale'] = this.isStale;
return data;
}
}
class Products {
int ? id;
String ? title;
String ? image;
String ? imageType;
Products({this.id, this.title, this.image, this.imageType});
Products.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
image = json['image'];
imageType = json['imageType'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['title'] = this.title;
data['image'] = this.image;
data['imageType'] = this.imageType;
return data;
}
}
if you want any further info please comment below thank you!
This is most likely causing your error:
List<dynamic> body = cnv.jsonDecode(res.body);
You need to access the list inside your decoded body, which is at key : "products", to do so, try:
List<dynamic> body = cnv.jsonDecode(res.body)["products"];
Future<void> getData() async {
http.Response res = await http.get(Uri.parse('https://api.spoonacular.com/food/products/search?query=pizza&apiKey=8fe91444f092411fa6011b71fd6e582d'));
var body = jsonDecode(res.body);
Iterable list = body['products'];
modell = list.map((e) => recipes.fromJson(e)).toList();
}
Try use iterable if your json is nested.

GET Request in Flutter

i start yesteraday with flutter and today i have a problem with GET request.
It looks like I can't get data from my URL, I have no idea why when I paste it into my browser everything works
I tried to get one single User object, but nothing work for me :(
my code,
User.dart
class User{
int id;
String firstName;
String lastName;
String email;
User(this.id, this.firstName, this.lastName, this.email);
User.fromJson(Map<String,dynamic> json){
id = json['id'];
firstName = json['firstName'];
lastName = json['lastName'];
email = json['email'];
}
}
my GET function:
Future<User> getCurrentUser() async {
String url = 'http://10.0.2.2:80/user/current';
final response =
await http.get(url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
return User.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
my widget:
class UserPageState extends State<UserPage>{
Future<List<dynamic>> _user;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (context) => Container(
child: FutureBuilder(
future: getCurrentUser(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasData ){
return Container(
child: Center(child: Text(snapshot.data['firstName']),),
);
}else {
return Text('NOT LOAD');
}
},
),
),
),
);
}
}
when i paste my url into browser it show me:
{
createdAt: 1584905291338,
updatedAt: 1584905291338,
id: 3,
firstName: "name",
lastName: "surname",
email: "surname#name.com",
admin: false
}
I don't have any more idea what i can do it,
PLEASE HELP ME :(
First of all, I would recommend, that you fetch your data from the initState in the StatefulWidget, and not within the build method. Otherwise, on every rebuild, the data is fetched newly via http.get. In your FutureBuilder widget you use then future: _user
class UserPage extends StatefulWidget {
UserPage({Key key}) : super(key: key);
#override
UserPageState createState() => UserPageState();
}
class UserPageState extends State<UserPage>{
Future<User> _user;
#override
void initState() {
super.initState();
_user = getCurrentUser();
}
#override
Widget build(BuildContext context) {
... // your code here
To answer your question and why the user class and its data isn't filled. You have to return the data from the function User.fromJson(...), otherwise it gets lost
class User{
int id;
String firstName;
String lastName;
String email;
User(this.id, this.firstName, this.lastName, this.email);
factory User.fromJson(Map<String,dynamic> json){
return User(
json['id'],
json['firstName'],
json['lastName'],
json['email'],
);
}
}
class User{
int id;
String firstName;
String lastName;
String email;
// For me, it's better to use named parameter to make it easier to read
User({this.id, this.firstName, this.lastName, this.email});
// this doesn't return User object
User.fromJson(Map<String,dynamic> json){
id = json['id'];
firstName = json['firstName'];
lastName = json['lastName'];
email = json['email'];
}
factory User.fromJson(Map<String,dynamic> json){
return User(
id: json['id'],
firstName : json['firstName '],
lastName : json['lastName '],
email : json['email '],
);
}
}