How can I parse this api json with flutter? - json

I am pretty new to coding. I finished all of the UI of an app for myself but I cannot figure out how to input the data from an api into my app.
I have been trying for over a week. Read so many articles and videos but this api never works. I have come to the conclusion that I am doing something wrong with the fetching part. Maybe because everything I read or watch demonstrates with a List instead of a Map.
Here is a copy of my code.
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<Stock> futureStock;
#override
void initState() {
super.initState();
futureStock = fetchStock();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: FutureBuilder<Stock>(
future: futureStock,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.companyName);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
),
);
}
}
Future<Stock> fetchStock() async {
final response = await http.get(
'https://sandbox.iexapis.com/stable/stock/aapl/stats?token=Tsk_38ddda0b877a4510b42a37ae713cdc96');
if (response.statusCode == 200) {
return Stock.fromJson(json.decode(response.body));
} else {
throw Exception('Fail to load');
}
}
Stock stockFromJson(String str) => Stock.fromJson(json.decode(str));
String stockToJson(Stock data) => json.encode(data.toJson());
class Stock {
Stock({
this.week52Change,
this.week52High,
this.week52Low,
this.marketcap,
this.employees,
this.day200MovingAvg,
this.day50MovingAvg,
this.float,
this.avg10Volume,
this.avg30Volume,
this.ttmEps,
this.ttmDividendRate,
this.companyName,
this.sharesOutstanding,
this.maxChangePercent,
this.year5ChangePercent,
this.year2ChangePercent,
this.year1ChangePercent,
this.ytdChangePercent,
this.month6ChangePercent,
this.month3ChangePercent,
this.month1ChangePercent,
this.day30ChangePercent,
this.day5ChangePercent,
this.nextDividendDate,
this.dividendYield,
this.nextEarningsDate,
this.exDividendDate,
this.peRatio,
this.beta,
});
double week52Change;
double week52High;
double week52Low;
int marketcap;
int employees;
double day200MovingAvg;
double day50MovingAvg;
int float;
double avg10Volume;
double avg30Volume;
double ttmEps;
double ttmDividendRate;
String companyName;
int sharesOutstanding;
double maxChangePercent;
double year5ChangePercent;
double year2ChangePercent;
double year1ChangePercent;
double ytdChangePercent;
double month6ChangePercent;
double month3ChangePercent;
double month1ChangePercent;
double day30ChangePercent;
double day5ChangePercent;
dynamic nextDividendDate;
double dividendYield;
DateTime nextEarningsDate;
DateTime exDividendDate;
double peRatio;
double beta;
factory Stock.fromJson(Map<String, dynamic> json) => Stock(
week52Change: json["week52change"].toDouble(),
week52High: json["week52high"].toDouble(),
week52Low: json["week52low"].toDouble(),
marketcap: json["marketcap"],
employees: json["employees"],
day200MovingAvg: json["day200MovingAvg"].toDouble(),
day50MovingAvg: json["day50MovingAvg"].toDouble(),
float: json["float"],
avg10Volume: json["avg10Volume"].toDouble(),
avg30Volume: json["avg30Volume"].toDouble(),
ttmEps: json["ttmEPS"].toDouble(),
ttmDividendRate: json["ttmDividendRate"].toDouble(),
companyName: json["companyName"],
sharesOutstanding: json["sharesOutstanding"],
maxChangePercent: json["maxChangePercent"].toDouble(),
year5ChangePercent: json["year5ChangePercent"].toDouble(),
year2ChangePercent: json["year2ChangePercent"].toDouble(),
year1ChangePercent: json["year1ChangePercent"].toDouble(),
ytdChangePercent: json["ytdChangePercent"].toDouble(),
month6ChangePercent: json["month6ChangePercent"].toDouble(),
month3ChangePercent: json["month3ChangePercent"].toDouble(),
month1ChangePercent: json["month1ChangePercent"].toDouble(),
day30ChangePercent: json["day30ChangePercent"].toDouble(),
day5ChangePercent: json["day5ChangePercent"].toDouble(),
nextDividendDate: json["nextDividendDate"],
dividendYield: json["dividendYield"].toDouble(),
nextEarningsDate: DateTime.parse(json["nextEarningsDate"]),
exDividendDate: DateTime.parse(json["exDividendDate"]),
peRatio: json["peRatio"].toDouble(),
beta: json["beta"].toDouble(),
);
Map<String, dynamic> toJson() => {
"week52change": week52Change,
"week52high": week52High,
"week52low": week52Low,
"marketcap": marketcap,
"employees": employees,
"day200MovingAvg": day200MovingAvg,
"day50MovingAvg": day50MovingAvg,
"float": float,
"avg10Volume": avg10Volume,
"avg30Volume": avg30Volume,
"ttmEPS": ttmEps,
"ttmDividendRate": ttmDividendRate,
"companyName": companyName,
"sharesOutstanding": sharesOutstanding,
"maxChangePercent": maxChangePercent,
"year5ChangePercent": year5ChangePercent,
"year2ChangePercent": year2ChangePercent,
"year1ChangePercent": year1ChangePercent,
"ytdChangePercent": ytdChangePercent,
"month6ChangePercent": month6ChangePercent,
"month3ChangePercent": month3ChangePercent,
"month1ChangePercent": month1ChangePercent,
"day30ChangePercent": day30ChangePercent,
"day5ChangePercent": day5ChangePercent,
"nextDividendDate": nextDividendDate,
"dividendYield": dividendYield,
"nextEarningsDate":
"${nextEarningsDate.year.toString().padLeft(4, '0')}-${nextEarningsDate.month.toString().padLeft(2, '0')}-${nextEarningsDate.day.toString().padLeft(2, '0')}",
"exDividendDate":
"${exDividendDate.year.toString().padLeft(4, '0')}-${exDividendDate.month.toString().padLeft(2, '0')}-${exDividendDate.day.toString().padLeft(2, '0')}",
"peRatio": peRatio,
"beta": beta,
};
}
Any help would be greatly appreciated!
I followed the official example from https://flutter.dev/docs/cookbook/networking/fetch-data

I have tested your code and can confirm it is working fine.
But if you are running the release build of your app, you need to add the following line into your AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET"/>

Related

displaying Json data as a list

I have a json file that i'm trying to display as a list in my app.
here is the json file and how it is laid out:
{
"peoplesnames": [
"name1",
"name2",
"name3",
"name4",
"name5",
"name6",
"name7",
"name8"
]
}
and here is the code from my app:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class test extends StatefulWidget {
const test({Key? key}) : super(key: key);
#override
State<test> createState() => _testState();
}
class _testState extends State<test> {
List<String> peopleNames = [];
void getData() async {
http.Response response = await http.get(
Uri.parse('www.genericwebsite.com'),
);
if (response.statusCode == 200) {
String data = response.body;
final names = jsonDecode(data);
peopleNames.addAll((names['peoplesnames'] as List));
setState(() {});
return names;
} else {
print(response.statusCode);
}
}
#override
Widget build(BuildContext context) {
getData();
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: peopleNames.length,
itemBuilder: (context, index) {
return Text(peopleNames[index].toString());
}),
);
}
}
The problem seems to be coming from as List in the following line of code:
peopleNames.addAll((names['peoplesnames'] as List));
when as List is there I get the followiing red underline error and the code won't run.
The argument type 'List' can't be assigned to the parameter type 'Iterable'.
then, If i remove as List, the red line goes away but when I run the code, i get this error in the console
E/flutter ( 7999): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'List' is not a subtype of type 'Iterable'
I know the app is talking to the server correctly because if i replace
peopleNames.addAll((names['peoplesnames'] as List));
setState(() {});
return names;
with print(names), and run it, the names print in the console.
any help fixing this would be greatly appreciated.
cheers
Here is your answer
void convertJsonToList() {
String jsonData = '''
{
"peoplesnames": [
"name1",
"name2",
"name3",
"name4",
"name5",
"name6",
"name7",
"name8"
]
}
''';
Map<String, dynamic> jsonMap = jsonDecode(jsonData);
peoplesNamesList = List<String>.from(jsonMap['peoplesnames']);
print(peoplesNamesList);
}
Try this:
peopleNames.addAll((names['peoplesnames'].toList()));

Why isn't my API data showing in a list view, when the GET request is successful?

I am working with flutter for the first time and having issues understanding why my data will not show. For context, the API returns a list of (physical) libraries and their current occupancy. I have correctly implemented an API get request, got the data outputted in the terminal (printed) and thus I know my API call is working. I also implemented the data received from the JSON as a list using my data model, and then I created a body with the library name and occupancy as a ListTile. Nothing is shown when compiled on the device screen, just a blank screen, no circular progress indicator either.
Here is my home page:
import 'package:flutter/material.dart';
import '../models/post.dart';
import '../services/remote_service.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// Declare a list of Libraries
List<Libraries> _libraries = [];
#override
void initState() {
super.initState();
// Call the getPosts function when the HomePage is initialized
_getPosts();
}
// Function to make the GET request and store the response in a list of Libraries
void _getPosts() async {
var api = getDataAPI();
var librariesJson = await api.getPosts();
// Use the librariesFromJson function to convert the JSON string to a list of Libraries
setState(() {
_libraries = librariesFromJson(librariesJson!) as List<Libraries>;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Library Occupancy'),
),
body: _libraries == null
? const Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: _libraries.length,
itemBuilder: (context, index) {
// Display the library name and occupancy in a ListTile
return ListTile(
title: Text(_libraries[index].webster.occupancy),
subtitle:
Text(_libraries[index].webster.lastRecordTime.toString()),
);
},
),
);
}
}
Here is my API request code (remote_service.dart):
// ignore_for_file: camel_case_types
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:xconcordia/models/post.dart';
class getDataAPI {
Future<String?> getPosts() async {
var credentials = '520:276377ba5206683e51d50fb86c378dc5';
// Encode the credentials in base64 format
var base64Credentials = base64Encode(utf8.encode(credentials));
var headers = {'Authorization': 'Basic $base64Credentials'};
var request = http.Request('GET',
Uri.parse('https://opendata.concordia.ca/API/v1/library/occupancy/'));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
String json = await response.stream.bytesToString();
// ignore: await_only_futures
Libraries library = await librariesFromJson(json);
print("webster: " + library.webster.occupancy);
return library.webster.occupancy;
} else {
print(response.statusCode);
}
return null;
}
}
And finally, here is my JSON data model:
import 'dart:convert';
Libraries librariesFromJson(String str) => Libraries.fromJson(json.decode(str));
String librariesToJson(Libraries data) => json.encode(data.toJson());
class Libraries {
Libraries({
required this.webster,
required this.vanier,
required this.greyNuns,
});
GreyNuns webster;
GreyNuns vanier;
GreyNuns greyNuns;
factory Libraries.fromJson(Map<String, dynamic> json) => Libraries(
webster: GreyNuns.fromJson(json["Webster"]),
vanier: GreyNuns.fromJson(json["Vanier"]),
greyNuns: GreyNuns.fromJson(json["GreyNuns"]),
);
Map<String, dynamic> toJson() => {
"Webster": webster.toJson(),
"Vanier": vanier.toJson(),
"GreyNuns": greyNuns.toJson(),
};
}
class GreyNuns {
GreyNuns({
required this.occupancy,
required this.lastRecordTime,
});
String occupancy;
DateTime lastRecordTime;
factory GreyNuns.fromJson(Map<String, dynamic> json) => GreyNuns(
occupancy: json["Occupancy"],
lastRecordTime: DateTime.parse(json["LastRecordTime"]),
);
Map<String, dynamic> toJson() => {
"Occupancy": occupancy,
"LastRecordTime": lastRecordTime.toIso8601String(),
};
}
Also, when I run this code, here is the terminal output:
Performing hot restart...
Restarted application in 302ms.
flutter: webster: .0000
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: FormatException: Unexpected character (at character 1)
.0000
^
#0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
#1 _ChunkedJsonParser.parseNumber (dart:convert-patch/convert_patch.dart:1250:9)
#2 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:915:22)
#3 _parseJson (dart:convert-patch/convert_patch.dart:35:10)
#4 JsonDecoder.convert (dart:convert/json.dart:612:36)
#5 JsonCodec.decode (dart:convert/json.dart:216:41)
#6 librariesFromJson (package:xconcordia/models/post.dart:3:68)
#7 _HomePageState._getPosts.<anonymous closure> (package:xconcordia/views/home_page.dart:28:20)
#8 State.setState (package:flutter/src/widgets/framework.dart:1114:30)
#9 _HomePageState._getPosts (package:xconcordia/views/home_page.dart:27:5)
<asynchronous suspension>
Modify Your Model Class
Convert the data to String in modal class:
factory GreyNuns.fromJson(Map<String, dynamic> json) => GreyNuns(
occupancy: json["Occupancy"].toString(),
lastRecordTime: DateTime.parse(json["LastRecordTime"].toString()),
);

A RenderFlex overflowed by 99397 pixels on the bottom

import 'package:flutter/material.dart';
import 'package:http_request/carditem.dart';
import 'package:http_request/user_data.dart';
// here we chose to have statefull widget because the state needs to be updated and we need to update some variables according to some conditions.
class UserScreen extends StatefulWidget {
const UserScreen({Key key}) : super(key: key);
#override
_UserScreenState createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
// here we created a variable to keep our information in it . this information comes from our user data class where we get the user data from http requests.
Map<String, dynamic> userinfo = {};
// this method is called as soon as the main widget is created . we call our http method here to have the live data as soon as we open the app .be aware that we cant use async and await here . we just call the method.
#override
void initState() {
super.initState();
getData();
}
// here we get hte live data from our userdata class .
Future getData() async {
//we create a userData object to get access to the getuserdata method.
UserData userData = UserData();
//we handle any error here
try {
// here we create a variable to the exact same type we are expecting .
//then we wait for the result of calling our userdata information.
Map<String, dynamic> data = await userData.getUserData();
// we call setState because we need to update a certain value here.
setState(() {
//we assign the the value of data to our variable called userinfo .try the reaosn we see no error behind them is that they are the same type.
userinfo = data;
});
// we catch errors here .
} catch (e) {
print(e);
}
}
// our nice build method ...this method is from our stateful class.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Work Harder'),
centerTitle: true,
),
body: ListView.builder(
itemBuilder: (context, index) => CardItem(
firstName: userinfo['firstName'],
avatarLink: userinfo['avatarLink'],
id: userinfo['id'],
lastName: userinfo['lastName'],
email: userinfo['email'],
),
),
);
}
}
as you can see here is my user_screen dart file the problem is when i hot reload the app is see the renderflex error, while everything seems fine. im a begginner in flutter and i would really appreciate your help.
i have tried singlechild scrollview , list view , expanded widget , but it doesn't work . please help me hotrestart may app without these long errors
import 'package:flutter/material.dart';
// we chose stateless because we don't need to change the state of our app.
class CardItem extends StatelessWidget {
const CardItem({
Key key,
this.firstName,
this.email,
this.avatarLink,
this.id,
this.lastName,
}) : super(key: key);
final String firstName;
final String email;
final String avatarLink;
final String id;
final String lastName;
#override
Widget build(BuildContext context) {
return Card(
color: Colors.lightBlueAccent[200],
elevation: 3,
shadowColor: Colors.blue[100],
child: Column(
children: [
Stack(
children: [
ListTile(
leading: Icon(Icons.check_box),
trailing: CircleAvatar(
child: Image.network(avatarLink),
),
title: Text(firstName),
subtitle: Text(lastName),
),
Positioned(
left: 48,
top: 15,
child: Text(
id,
style: TextStyle(
color: Colors.white70,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
Positioned(
left: 120,
top: 30,
child: Text(
'Email : $email',
style: TextStyle(
color: Colors.blue[900].withOpacity(0.6),
),
),
),
],
),
],
),
);
}
}
here is my card widget , if it helps.
import 'dart:convert';
import 'package:http/http.dart' as http;
// this is the file for our main http requests.
class UserData {
UserData({
this.firstName,
this.lastName,
this.email,
this.id,
this.avatarLink,
});
final String firstName;
final String lastName;
final String email;
final String id;
final String avatarLink;
//this method is response for getting the live data we want also its responsible for decoding it with 'dart convert' library and returning the result as an output.
Future getUserData() async {
//the url we are working with
final String stringUrl = 'https://reqres.in/api/users?page=2';
//sending the request to web and storing the result to a variable. we also have to wait for the results . (asynchronous operation).
http.Response response = await http.get(
Uri.parse(stringUrl),
);
//we create a variable to the exact type of our output . we want to add our items to this map to use it in the main screen.
Map<String, dynamic> userdetails = {};
//here we want to check if our request was successful if so, we continue our operation and if not we throw an error .
if (response.statusCode == 200) {
// here we are decoding the data that we got from our request above to a variable of type map.
Map<String, dynamic> decodedData = jsonDecode(response.body);
//here we try to iterate through a map .. but im not sure if its correct or not .
for (var user in decodedData.values) {
Map<String, dynamic> myusersInfo = {
'firstName': decodedData['data'][0]['first_name'],
'lastName': decodedData['data'][0]['last_name'],
'email': decodedData['data'][0]['email'],
'id': decodedData['data'][0]['id'].toString(),
'avatarLink': decodedData['data'][0]['avatar'],
};
// here we are trying to add the items to the map specified.
userdetails.addEntries(myusersInfo.entries);
return userdetails;
}
} else {
print(response.statusCode);
throw 'Problem with the get request';
}
}
}
the whole goal of this app was to practice some http request.
the last file I have in this app . I just added this maybe it helps you . thanks in advance.
A Column likes to expand until infinity.
This can be solved by putting an intrinsicHeight around the Column as followed:
This class is useful, for example, when unlimited height is available and you would like a child that would otherwise attempt to expand infinitely to instead size itself to a more reasonable height.
IntrinsicHeight(
child: Column(
children: [
],
)
);
https://api.flutter.dev/flutter/widgets/IntrinsicHeight-class.html
try column inside SingleChildScrollView

How do I initialize my json response in another class that depends on a search input in flutter?

this is my first question here on stackoverflow.
I'm working on my first real app after attending a few CS classes at University and some courses on Udemy. So I'm lacking a lot of software engineering knowledge.
My goal: I want to build a search for stocks by using an external API endpoint. For that, I have created 4 dart files to handle the searchscreen with inputs (My UI), networking, parsing, and basically returning the data.
My NetworkAPI class to handle all sorts of network requests looks like this. I'm trying to use the jsonDecode already here and returning that. This class waits for an URL that will be put together in another class (financeData):
class NetworkAPI {
final String url;
NetworkAPI(this.url);
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
String data = response.body;
return jsonDecode(data);
} else {
print(response.statusCode);
}
}
}
This is basically the Json I want to parse. If I understood the theory correctly it's a map with a list of objects.
{
"bestMatches": [
{
"1. symbol": "TESO",
"2. name": "Tesco Corporation USA",
"3. type": "Equity",
"4. region": "United States",
"5. marketOpen": "09:30",
"6. marketClose": "16:00",
"7. timezone": "UTC-04",
"8. currency": "USD",
"9. matchScore": "0.8889"
}
{....}
]
}
To parse this, I saw some really good explanations here on stack overflow. I'm basically trying to retrieve the information I'm interested in.
class SearchOutput {
final List<BestMatch> bestMatches;
SearchOutput({this.bestMatches});
factory SearchOutput.fromJson(Map<String, dynamic> parsedJson){
var list = parsedJson['bestMatches'] as List;
print(list.runtimeType);
List<BestMatch> searchResultList = list.map((i) => BestMatch.fromJson(i)).toList();
return SearchOutput(
bestMatches: searchResultList,
);
}
}
class BestMatch {
String symbol;
String name;
String type;
String region;
String currency;
BestMatch({
this.symbol,
this.name,
this.type,
this.region,
this.currency,
});
factory BestMatch.fromJson(Map<String, dynamic> parsedJson){
return BestMatch(
symbol: parsedJson["1. symbol"],
name: parsedJson["2. name"],
type: parsedJson["3. type"],
region: parsedJson["4. region"],
currency: parsedJson["8. currency"],
);
}
}
Now I created a class with a method that should return all my data and format it into a list. The URL still needs an searchInput, which will be handed over from a TextField Widget in the UI.
const apiKey = 'demo';
const alphaVantageSearchUrl =
'https://www.alphavantage.co/query?function=SYMBOL_SEARCH';
class FinanceData {
Future<dynamic> getSearchData(String searchInput) async {
var url = '$alphaVantageSearchUrl&keywords=$searchInput&apikey=$apiKey';
NetworkAPI networkAPI = NetworkAPI(url);
var searchData = await networkAPI.getData();
SearchOutput searchOutput = new SearchOutput.fromJson(searchData);
return searchOutput;
}
}
Testing with some print statements seems to fullfill my goal of being able to access the data. For example printing out the name of the second object out of my response.
print(searchOutput.bestMatches[1].name);
The last file is my UI where we have a TextField, that I push to the financeData class in order to build the URL. Currently, my goal would be, to be able to show just the name of any given object in my response in the UI. I have no idea how to initialize my financeDate and how to use the return from my finaceData class in the UI. (I took some design styles out of the code snippet).
class SearchScreenWatchlist extends StatefulWidget {
#override
_SearchScreenWatchlistState createState() => _SearchScreenWatchlistState();
}
class _SearchScreenWatchlistState extends State<SearchScreenWatchlist> {
String searchInput;
FinanceData financeData = FinanceData();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Container(
child: TextField(
onChanged: (value) {
searchInput = value;
},
),
),
TextButton(
onPressed: () {
financeData.getSearchData(searchInput);
setState(() {
});
},
child: Text('Search')),
Text(('Search Results for: $searchInput')),
Container(child: Text('**SHOW HERE THE NAME**')),
],
),
);
}
}
It would be my goal to show in the last container the name on any given object from my response for example RESPONSE.name[1]. Later on I will try to iterate throw all the objects and show a list of all names of the response.
Thanks a lot! I really appreciate your help!
I think changing SearchScreenWatchlist to the following should display the name of the first bestMatches entry after you pressed the Search button (if I didn't miss something).
Make sure to look further into setState and initState (And the StatefulWidget lifecycle in general). Also it may not be the most elegant way to initialize FinanceData() and SearchOutput() this way - However, awesome starter project!
class SearchScreenWatchlist extends StatefulWidget {
#override
_SearchScreenWatchlistState createState() => _SearchScreenWatchlistState();
}
class _SearchScreenWatchlistState extends State<SearchScreenWatchlist> {
String searchInput;
FinanceData financeData;
SearchOutput searchOutput;
#override
initState() {
super.initState();
financeData = FinanceData();
searchOutput = SearchOutput();
}
_handleButtonPress() async {
final fetchedSearchOutput = await financeData.getSearchData(searchInput);
setState(() {
searchOutput = fetchedSearchOutput;
});
}
_buildSearchResult() {
if(searchOutput.bestMatches != null && searchOutput.bestMatches.isNotEmpty) {
return Text(searchOutput.bestMatches.first.name);
}
else {
return Text("No data fetched");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Container(
child: TextField(
onChanged: (value) {
setState(() {
searchInput = value;
});
},
),
),
TextButton(
onPressed: () => _handleButtonPress(),
child: Text('Search'),
),
Text(('Search Results for: $searchInput')),
Container(
child: _buildSearchResult(),
),
],
),
);
}
}

Fetch Json data flutter

i'm confusing with this kind of json.
because i never see someone explain about this kind of json data.
i get my jsondata from a link, and the json data show like this
{
"data": [
{
"jenis_komoditas": "Gabah IR 64 KP",
"harga": "5400",
"satuan": "Kg",
"persen": null,
"perubahan": "0",
"selisi": "0",
"image": "assets\/thumb\/gabah.png"
},
{
"jenis_komoditas": "Gabah IR 64 KG",
"harga": "6200",
"satuan": "Kg",
"persen": null,
"perubahan": "0",
"selisi": "0",
"image": "assets\/thumb\/gabah1.png"
}
]
}
it gets error.
can someone help me how to get the data from first json type?
You can parse your full json string with
Payload payload = payloadFromJson(jsonString);
print('${payload.data[0].jenisKomoditas}');
Related Class
// To parse this JSON data, do
//
// final payload = payloadFromJson(jsonString);
import 'dart:convert';
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
String payloadToJson(Payload data) => json.encode(data.toJson());
class Payload {
List<Datum> data;
Payload({
this.data,
});
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
String jenisKomoditas;
String harga;
String satuan;
dynamic persen;
String perubahan;
String selisi;
String image;
Datum({
this.jenisKomoditas,
this.harga,
this.satuan,
this.persen,
this.perubahan,
this.selisi,
this.image,
});
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
jenisKomoditas: json["jenis_komoditas"],
harga: json["harga"],
satuan: json["satuan"],
persen: json["persen"],
perubahan: json["perubahan"],
selisi: json["selisi"],
image: json["image"],
);
Map<String, dynamic> toJson() => {
"jenis_komoditas": jenisKomoditas,
"harga": harga,
"satuan": satuan,
"persen": persen,
"perubahan": perubahan,
"selisi": selisi,
"image": image,
};
}
full code
import 'package:flutter/material.dart';
// To parse this JSON data, do
//
// final payload = payloadFromJson(jsonString);
import 'dart:convert';
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
String payloadToJson(Payload data) => json.encode(data.toJson());
class Payload {
List<Datum> data;
Payload({
this.data,
});
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
String jenisKomoditas;
String harga;
String satuan;
dynamic persen;
String perubahan;
String selisi;
String image;
Datum({
this.jenisKomoditas,
this.harga,
this.satuan,
this.persen,
this.perubahan,
this.selisi,
this.image,
});
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
jenisKomoditas: json["jenis_komoditas"],
harga: json["harga"],
satuan: json["satuan"],
persen: json["persen"],
perubahan: json["perubahan"],
selisi: json["selisi"],
image: json["image"],
);
Map<String, dynamic> toJson() => {
"jenis_komoditas": jenisKomoditas,
"harga": harga,
"satuan": satuan,
"persen": persen,
"perubahan": perubahan,
"selisi": selisi,
"image": image,
};
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String jsonString = '''
{
"data": [
{
"jenis_komoditas": "Gabah IR 64 KP",
"harga": "5400",
"satuan": "Kg",
"persen": null,
"perubahan": "0",
"selisi": "0",
"image": "assets\/thumb\/gabah.png"
},
{
"jenis_komoditas": "Gabah IR 64 KG",
"harga": "6200",
"satuan": "Kg",
"persen": null,
"perubahan": "0",
"selisi": "0",
"image": "assets\/thumb\/gabah1.png"
}
]
}
''';
void _incrementCounter() {
Payload payload = payloadFromJson(jsonString);
print('${payload.data[0].jenisKomoditas}');
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Output
I/flutter (23421): Gabah IR 64 KP
you are getting data in form of json array so you can simply call it iteratively from the object. like this
if you get data in data variable:
final jsondata=json.decode(data);
for (var dataf in jsondata['data']){
print(dataf['jenis_komoditas']);
}