I am currently building an app to get a data from a json api.
I want to get the number 54 from the json code.
here is the json link
I have tried making model class of the json api here
class TeerModel{
String text;
TeerModel(this.text);
TeerModel.fromJson(Map<String, dynamic>parsedJson){
text = parsedJson['text'];
}
}
But I can't get the result so i removed it
Here is the code
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'models/teer_model.dart';
import 'dart:convert';
class Appss extends StatefulWidget {
#override
_AppssState createState() => _AppssState();
}
class _AppssState extends State<Appss> {
String result = "1S";
void fetchData ()async{
var response1 = await get("http://motyar.info/webscrapemaster/api/?url=http://teertoday.com/&xpath=/html/body/div[5]/div/table/tbody/tr[3]/td[1]#vws");
var teerModel = json.decode(response1.body);
var line = teerModel["text"].replaceAll(new RegExp(r"(\s\n)"), "");
print(line);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Teer result"),),
floatingActionButton: FloatingActionButton(
onPressed: fetchData,
),
body: Center(
child: Text("The result is: $result"),
),
),
);
}
}
I only want to get the number 54 from "text" so I use regex
I expected the output will be 54 but instead I get this error
If you look at your json, you will see that it is entirely surrounded by [...], meaning that it is a json array. json.decode will convert this into a Dart List<Map<String, dynamic>>. It looks like you want the first / zero'th element of this array/list.
Change:
var line = teerModel["text"].replaceAll(new RegExp(r"(\s\n)"), "");
to
var line = teerModel[0]["text"].replaceAll(new RegExp(r"(\s\n)"), "");
Don't forget to call setState so that your widget rebuilds itself.
Related
I am currently building an app to get a data from a json api.
I want to get the number 54 from the json code.
here is the json link
I have tried making model class of the json api here
class TeerModel{
String text;
TeerModel(this.text);
TeerModel.fromJson(Map<String, dynamic>parsedJson){
text = parsedJson['text'];
}
}
But I can't get the result so i removed it
Here is the code
import 'package:flutter/material.dart';
import 'package:http/http.dart' show get;
import 'models/teer_model.dart';
import 'dart:convert';
class Appss extends StatefulWidget {
#override
_AppssState createState() => _AppssState();
}
class _AppssState extends State<Appss> {
String result = "1S";
void fetchData ()async{
var response1 = await get("http://motyar.info/webscrapemaster/api/?url=http://teertoday.com/&xpath=/html/body/div[5]/div/table/tbody/tr[3]/td[1]#vws");
var teerModel = json.decode(response1.body);
var line = teerModel["text"].replaceAll(new RegExp(r"(\s\n)"), "");
print(line);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Teer result"),),
floatingActionButton: FloatingActionButton(
onPressed: fetchData,
),
body: Center(
child: Text("The result is: $result"),
),
),
);
}
}
I only want to get the number 54 from "text" so I use regex
I expected the output will be 54 but instead I get this error
If you look at your json, you will see that it is entirely surrounded by [...], meaning that it is a json array. json.decode will convert this into a Dart List<Map<String, dynamic>>. It looks like you want the first / zero'th element of this array/list.
Change:
var line = teerModel["text"].replaceAll(new RegExp(r"(\s\n)"), "");
to
var line = teerModel[0]["text"].replaceAll(new RegExp(r"(\s\n)"), "");
Don't forget to call setState so that your widget rebuilds itself.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:carousel_pro/carousel_pro.dart';
import 'package:http/http.dart' as http;
class Home extends StatelessWidget
{
#override
Widget build(BuildContext context)
{
return MyApp(post: fetchPost());
}
}
Future<Post> fetchPost() async {
final response = await http.get('https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro&explaintext&redirects=1&titles=Zambia');
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
class Post {
final int pageid;
final int ns;
final String title;
final String extract;
Post({this.pageid, this.ns, this.title, this.extract});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
pageid: json['pageid'],
ns: json['ns'],
title: json['title'],
extract: json['extract'],
);
}
}
class ImageCarousel extends StatelessWidget
{
final carousel = Carousel(
showIndicator: false,
boxFit: BoxFit.cover,
images: [
AssetImage('assets/images/animals.jpg'),
AssetImage('assets/images/bigfalls.jpg'),
AssetImage('assets/images/resort.jpg'),
AssetImage('assets/images/soca.jpg'),
AssetImage('assets/images/towncity.jpg')
],
animationCurve: Curves.fastOutSlowIn,
animationDuration: Duration(microseconds: 20000),
);
#override
Widget build(BuildContext context)
{
double screenHeight = MediaQuery.of(context).size.height / 3;
return ListView(
children: <Widget>[
Container(
height: screenHeight,
color: Colors.red,
child: carousel,
),
const Text('About Zambia', style: TextStyle(fontWeight: FontWeight.bold)),
],
);
}
}
class MyApp extends StatelessWidget {
final Future<Post> post;
MyApp({Key key, this.post}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Container(
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.title);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner
return CircularProgressIndicator();
},
),
);
}
}
I'm using the example in flutter's documentation on how to fetch data from the internet (https://flutter.io/docs/cookbook/networking/fetch-data), and in place of https://jsonplaceholder.typicode.com/posts/1 I'm using ( https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro&explaintext&redirects=1&titles=Zambia ) but for some reason, I can't get the information to be displayed on my App, forgive the ignorance but I'm new to programming and flutter...
You are parsing the json in the wrong way: the json from that url has a different structure, the keys you are trying to fetch are nested inside "query":{"pages":{"34415" while you are searching for them at the top level.
E.g. in this case, this :
pageid: json['pageid']
should be:
pageid: json['query']['pages']['34415']['pageid']
But it works only in this specific case. Instead, you should first fetch all the pages you get by that query from json['query']['pages'] then loop over the keys (the ids of every page got) and fetch the pages.
I am trying to fetch the data from json api and to be listed in the drop down list but i am hitting with The method 'map' was called on null error.
import "package:flutter/material.dart";
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() => runApp(MaterialApp(
title: "Hospital Management",
home: MyApp(),
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _mySelection;
final String url = "http://webmyls.com/php/getdata.php";
List data;
Future<String> getSWData() async {
var res = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
var resBody = json.decode(res.body);
setState(() {
data = resBody;
});
print(resBody);
return "Sucess";
}
#override
void initState() {
super.initState();
this.getSWData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Hospital Management"),
),
body: new Center(
child: new DropdownButton(
items: data.map((item) {
return new DropdownMenuItem(
child: new Text(item['item_name']),
value: item['id'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelection = newVal;
});
},
value: _mySelection,
),
),
);
}
}
The error from the debug consol
flutter: The method 'map' was called on null.
flutter: Receiver: null
flutter: Tried calling: map<DropdownMenuItem<String>>(Closure:
(dynamic) => DropdownMenuItem<String>)
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 Object.noSuchMethod
(dart:core/runtime/libobject_patch.dart:48:5)
I am expecting to show the list of data from the json api in the drop down menu. I am beginner to dart and flutter. Help me out to solve the error.
data is not initialized. It is set on getSWData which is async.
A possible solution could be to have data as emptyList as an initial value.
List data = List();
If you want to display DropdownButton based on data, you can use FutureBuilder and show loader or something till data comes from getSWData
Your Api http://webmyls.com/php/getdata.php returns a list not a map. Hence, it cannot have direct property advisor_report. Consider removing it.
Data should be changed inside setState.
You never called getSWData()
Below is more improved example.
import "package:flutter/material.dart";
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() => runApp(MaterialApp(
title: "Hospital Management",
home: MyApp(),
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _mySelection;
final String url = "http://webmyls.com/php/getdata.php";
List data;
Future<String> getSWData() async {
var res = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
var resBody = json.decode(res.body);
setState(() {
data = resBody;
});
print(resBody);
return "Sucess";
}
#override
void initState() {
super.initState();
this.getSWData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Hospital Management"),
),
body: new Center(
child: new DropdownButton(
items: data.map((item) {
return new DropdownMenuItem(
child: new Text(item['item_name']),
value: item['id'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelection = newVal;
});
},
value: _mySelection,
),
),
);
}
}
This is one official example of simple BarChart for Flutter app - https://google.github.io/charts/flutter/example/bar_charts/simple
I wood like fetch data from Internet for this chart. Here is the data - http://skazkimal.ru/hr-metrics/headcount.json
My code is not work, because method _createSampleData is async:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:hr_metrics/FetchChartData.dart';
import 'package:http/http.dart' as http;
class SalaryView extends StatelessWidget{
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('FFFFFFFFF'),
),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: new SalaryChart.withSampleData(),
),
);
}
}
class SalaryChart extends StatelessWidget{
final List<charts.Series> seriesList;
final bool animate;
SalaryChart(this.seriesList, {this.animate});
/// Creates a [BarChart] with sample data and no transition.
factory SalaryChart.withSampleData() {
return new SalaryChart(
_createSampleData(),
// Disable animations for image tests.
animate: true,
);
}
#override
Widget build(BuildContext context) {
// This is just a simple bar chart with optional property
// [defaultInteractions] set to true to include the default
// interactions/behaviors when building the chart.
// This includes bar highlighting.
//
// Note: defaultInteractions defaults to true.
//
// [defaultInteractions] can be set to false to avoid the default
// interactions.
return new charts.BarChart(
seriesList,
animate: animate,
defaultInteractions: true,
barRendererDecorator: new charts.BarLabelDecorator<String>(),
vertical: false,
);
}
/// Create one series with sample hard coded data.
static Future<List<charts.Series<ChartData, String>>> _createSampleData() async {
final data = await fetchData(http.Client());
return [
new charts.Series<ChartData, String>(
id: 'Numbers',
domainFn: (ChartData series, _) => series.period,
measureFn: (ChartData series, _) => series.count,
data: data,
labelAccessorFn: (ChartData series, _) => '${series.count.toString()}'
)
];
}
}
/// Sample ordinal data type.
class OrdinalSalary {
final String year;
final int salary;
OrdinalSalary(this.year, this.salary);
}
You cannot use an async method in a constructor like that. Instead, you should create an async method like so:
static Future<SalaryChart> withSampleData() => _createSampleData().then((data) => SalaryChart(data, animate: true));
Which you would use elsewhere:
SalaryChart myChart = await SalaryChart.withSampleData();
Creating a earthquake information app using this api:
https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson
But getting this error after running application:
Error: A value of type 'dart.core::List<#lib1::Data>' can't beassigned to a variable of type 'dart.core::List<#lib2::Data>'.
E/flutter ( 9986): Try changing the type of the left hand side, or casting the right hand side to 'dart.core::List<#lib2::Data>'.
E/flutter ( 9986): _quakes = quakes;
My flutter version: Flutter 0.5.7-pre.100 • channel master
Codes: api.dart
import 'dart:async';
import 'dart:convert';
import 'package:flutter_layout/project/quake/models/quake.dart';
import 'package:flutter_layout/project/quake/models/serializers.dart';
import 'package:http/http.dart' as http;
const String baseUrl = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson';
Future<List<Data>> getQuake() async {
final response = await http.get((Uri.parse(baseUrl)));
print("${response.toString()}");
Quake quake = serializers.deserializeWith(Quake.serializer, json.decode(response.body));
return quake.features.map((Properties properties) => properties.properties).toList();
}
quake.dart
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'quake.g.dart';
abstract class Quake implements Built<Quake, QuakeBuilder> {
BuiltList<Properties> get features;
Quake._();
factory Quake([updates(QuakeBuilder b)]) = _$Quake;
static Serializer<Quake> get serializer => _$quakeSerializer;
}
abstract class Properties implements Built<Properties, PropertiesBuilder> {
Data get properties;
Properties._();
factory Properties([updates(PropertiesBuilder b)]) = _$Properties;
static Serializer<Properties> get serializer => _$propertiesSerializer;
}
abstract class Data implements Built<Data, DataBuilder> {
double get mag;
String get place;
Data._();
factory Data([updates(DataBuilder b)]) = _$Data;
static Serializer<Data> get serializer => _$dataSerializer;
}
QuakeApp.dart
import 'package:flutter/material.dart';
import 'QuakeListView.dart';
import 'models/api.dart';
import 'models/quake.dart';
class QuakeApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return QuakeAppState();
}
}
class QuakeAppState extends State<QuakeApp>{
List<Data> _quakes = [];
#override
void initState() {
super.initState();
getQuake().then((quakes){
_quakes = quakes;
});
}
List<QuakeListItem> buildListWidget(){
return _quakes.map((post) => QuakeListItem(
mag: post.mag,
place: post.place,
)).toList();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Quake App"),
centerTitle: true,
),
body: RefreshIndicator(
onRefresh: () async{
getQuake().then((quakes){
setState(() {
_quakes = quakes;
print("${quakes.length}");
});
});
},
child: AnimatedCrossFade(
duration: Duration(microseconds: 300),
firstChild: Center(
child: CircularProgressIndicator(),
),
secondChild: ListView(
children: buildListWidget(),
),
crossFadeState: _quakes != null ? CrossFadeState.showSecond : CrossFadeState.showFirst,
),
),
);
}
}
Any Solution?
I guess this is the known issue https://github.com/dart-lang/sdk/issues/33076
Do not use relative imports in lib/main.dart (only 'package:...' imports)
and do not import lib/main.dart from any other file.