Depending dropdown data showing Faild assertion error - json

I need to display list of Lab name in the dropdown list and when I click Lab name it need to go to respective Test of that Lab. I tried with different possible way to achieve this, following approach seems to understandable for me but its showing some kind of Error
The following assertion was thrown building MyHomePage(dirty, state: _MyHomePageState#ec203):
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 378 pos 10: 'data != null'
//CALLING LAB API HERE
List allLabList;
String _myLab;
String allLabInfoUrl = 'http://myurldjhjhfsf';
Future<String> _getLabList() async {
await http.post(allLabInfoUrl, body: {
}).then((response) {
var data = json.decode(response.body);
// print(data);
setState(() {
allLabList = data['Partner'];
});
});
}
// Get TEST information by API
List testList;
String _myTest;
String allTestInfoUrl ='http://putmyurlhere';
Future<String> _getTestList() async {
await http.post(allTestInfoUrl, body: {
"TestId": _myLab,
}).then((response) {
var data = json.decode(response.body);
setState(() {
testList = data['Data'];
});
});
}
}

Related

Can't manage to fetch data from a second JSON file

I'm trying to use a fetched data from a JSON file to make another fetch on a second screen.
Let's say I have a JSON file that was fetched via www.fruits.com/data. Then one of the fruits has an ID of 1. In order to have more information about this fruit, I have to access another JSON file on www.fruits.com/data/1.
I have both of these fetch functions to access JSON and drag said data:
List<Fruitmodel> parseFruit(String responseBody) {
var list = json.decode(responseBody) as List<dynamic>;
List<Fruitmodel> fruits = list.map((model) => Fruitmodel.fromJson(model)).toList();
return fruits;
}
List<FruitDetails> parseDetails(String responseBody) {
var list = json.decode(responseBody) as List<dynamic>;
List<FruitDetails> fruit_details = list.map((model) => FruitDetails.fromJson(model)).toList();
return fruit_details;
}
Future<List<FruitModel>> fetchFruit() async {
final response = await http.get(Uri.parse('https://fruits.com/data'));
if (response.statusCode == 200){
return compute(parseFruits, response.body);
}
else{
throw Exception('Failed to get fruits.');
}
}
Future<List<FruitDetails>> fetchDetails(int? a) async { //"int a" is to get the fruit's ID
String newUrl = 'https://fruits.com/data/' + a.toString();
final response = await http.get(Uri.parse(newUrl));
if (response.statusCode == 200){
return compute(parseDetails, response.body);
}
else{
throw Exception('Failed to get details.');
}
}
On my homepage, I used the first fetch function (FetchFruit), and managed to make a fruit list with the first JSON file by using Future Builder (snapshots), then my next task is to click on a fruit and show its details.
...
onTap:(){
Navigator.push(context,
new MaterialPageRoute(builder: (context)
=> DetailsPage(snapshot.data[index])));
...
So, on my next page, I'm initializing it with data from the fruit I've chosen. Then, I try to make the other fetch function (fetchDetails) by using said fruit's ID contained on the other JSON.
...
body: Center(
child: FutureBuilder(
future: fetchDetails(this.fruit.id), //Using ID to mount the correct URL
...
But... It doesn't work. I did a condition to tell me that if the snapshot has an error, it prints "Data not available" on the screen, and it does that instead of reading the second JSON file. What should I do for the second fetch to be done correctly?
In resume:
1st JSON file -> ID -> used to access 2nd JSON file -> not working
Try using this
String newUrl = 'https://fruits.com/data/$a';
and make sure the value won't be null.

Flutter/Dart Error - NoSuchMethodError (NoSuchMethodError: Class 'String' has no instance method 'map'

I receive an error that has something to do with JSON receiver inside Flutter/Dart.
Had to share in a docs file since the full json response is pretty long. It had like 15 columns error log
Detail Class
class Detail {
String kodkursus;
String namakursus;
String kursusdescription;
Detail(
{required this.kodkursus,
required this.namakursus,
required this.kursusdescription});
factory Detail.fromJson(Map<String, dynamic> json) {
return Detail(
kodkursus: json['crs_code'] as String,
namakursus: json['crs_title_bm'] as String,
kursusdescription: json['crs_description_bm'] as String,
);
}
}
Code
Future<dynamic> generateDetailList() async {
var url = 'http://10.0.2.2:81/login_testing/kursus_display.php';
var data = {'usr_id': widget.username2};
var response = await http.post(url, body: json.encode(data));
var list = json.decode(json.encode(response.body));
List<Detail> _detail =
list.map<Detail>((json) => Detail.fromJson(json)).toList();
detailDataSource = DetailDataSource(_detail);
return _detail;
}
Return (full error log)
NoSuchMethodError (NoSuchMethodError: Class 'String' has no instance method 'map'...
I fairly new to this Flutter/Dart but I got the feeling it had something to do with the json, it just I cant get my head over it
Please check your API response because this error generates when there are difference in datatype.
this error says your app response it in String and you are accessing this as map so please check your API response or
try to replace this :
var list = json.decode(json.encode(response.body));
with :
var list = json.decode(response.body);
because json.encode method encodes all list data and that values datatype is String so it gives error.
Replace your function generateDetailList as such:
Future<List<Detail>?> generateDetailList() async {
Uri url = Uri.parse('http://10.0.2.2:81/login_testing/kursus_display.php');
Map<String, String> data = {'usr_id': 'widget.username2'};
http.Response response = await http.post(url, body: json.encode(data));
// var list = json.decode(json.encode(response.body));
var responseMap = await jsonDecode(response.body);
if (response.statusCode == 200) {
List<Detail> _details =
responseMap.map<Detail>((x) => Detail.fromJson(x)).toList();
return _details;
} else {
return null;
}
}
And try not to use var everywhere.

Store a api response data in firebase collections using flutter

So, I have been making a post request to a REST API and I want to store the response data in the firebase cloud store collection.
What I have done so far:
I have created the model class for the response data and have written a function that will make this post-call.
I am not getting any such error but still, neither the response is getting printed in the console nor the data is being uploaded in the firebase.
Also, I have checked with almost all the StackOverflow questions that relate to my kind of problem.
Herewith I am attaching my code snippets:
Function:
//This function is only not getting called I don't know why.
final List<KycDetails> _kyc = [];
Dio dio = Dio();
TextEditingController aadhar = TextEditingController();
Future<List<KycDetails>> postData() async {
const String pathUrl = 'https://jsonplaceholder.typicode.com/posts';
dynamic data = {'title': aadhar.text, 'body': 'Flutter', 'userId': 1};
List<KycDetails> details = [];
var response = await dio.post(pathUrl,
data: data,
options: Options(
headers: {'Content-Type': 'application/json; charset=UTF-8'}));
if (response.statusCode == 200) {
print('ok');
var urjson = jsonDecode(response.data);
for (var jsondata in urjson) {
details.add(KycDetails.fromJson(jsondata));
}
}
return details;
}
Widget where I am calling the function and storing the data in firebase
InkWell(
hoverColor: Colors.red,
onTap: () async {
print('API CALLING');
await postData().then((value) {
setState(() {
_kyc.addAll(value);
});
print(value);
});
Map<String, String> data = {
"aadhar": aadhar.text,
"title": _kyc[0].title,
"userId": _kyc[0].userId.toString(),
};
FirebaseFirestore.instance.collection('kyc').add(data);
},
child: const Text('Submit'),
),
API response data:
{"title": "resume", "body": "Flutter", "userId": 1, "id": 101}
Model Class:
class KycDetails {
KycDetails({
required this.title,
required this.body,
required this.userId,
required this.id,
});
String title;
String body;
int userId;
int id;
factory KycDetails.fromJson(Map<String, dynamic> json) => KycDetails(
title: json["title"],
body: json["body"],
userId: json["userId"],
id: json["id"],
);
Map<String, dynamic> toJson() => {
"title": title,
"body": body,
"userId": userId,
"id": id,
};
}
I hope I have provided you with the necessary information
Am stuck on this problem for quite a few days Would appreciate it if anyone can solve my problem considering my code.
For starters, when you make a post request the success code you're looking for is 201 indicating that a resource has been successfully created.
So nothing in this code block will run.
if (response.statusCode == 200) {
print('ok');
var urjson = jsonDecode(response.data);
for (var jsondata in urjson) {
details.add(KycDetails.fromJson(jsondata));
}
}
response.data doesn't need jsonDecode here. It returns in the form of a map so you can cast it as such.
So this
var urjson = jsonDecode(response.data);
can be this
final urjson = response.data as Map<String, dynamic>;
As for this line
for (var jsondata in urjson) {
details.add(KycDetails.fromJson(jsondata));
}
The response is a single map, not a list. That single map is in the form of your KycDetails model so you don't need to loop through anything.
So you can create your object with your fromJson method.
final kycDetail = KycDetails.fromJson(urjson);
Then you can just do this to add a properly initiated KycDetails object to the list.
details.add(kycDetail);
If all you're trying to do is add a single object to Firebase then none of this in your onTap is necessary. Also trying to access the property at index 0 will not be the most recent addition to the list. You'd need to add the index of the last item in the list.
Map<String, String> data = {
"aadhar": aadhar.text,
"title": _kyc[0].title,
"userId": _kyc[0].userId.toString(),
};
FirebaseFirestore.instance.collection('kyc').add(data);
You can just add to Firebase from your postData function.
if (response.statusCode == 201) {
print('ok');
final urjson = response.data as Map<String, dynamic>;
final kycDetail = KycDetails.fromJson(urjson);
details.add(kycDetail);
FirebaseFirestore.instance.collection('kyc').add(kycDetail.toJson());
}

Flutter web json data not getit

i am new to flutter web but this error is crazy my func to get json data is
#override
Future<List<StoryEntity>> getNewAnimation(int id) async{
print("ali");
return (json.decode(
(await http.Client().get(Uri.parse('https://hekayatname.ir/home/getanimation')))
.body)['list'] as List)
.map(
(e) => StoryEntity(
title: e['fullname'],
imagePath: e['logo_url'],
description: "e['description']",
rating: 1,
galleryImagesPath: [],
id: e['id'],
producer: e['address'],
),
).toList();
}
but i recive nothing in flutter.
in web browser my data is like this just go to this link
https://hekayatname.ir/home/getanimation
i change the code to this
Future<List<StoryEntity>> getNewAnimation(int id) async{
print("1");
final response = await http.Client().get(Uri.parse("https://hekayatname.ir/home/getaudioestory"));
if(response.statusCode == 200){
print("2");
}
else{
print("3");
print(response.statusCode);
}
}
i have nothing to both if and else
if not work,else not work.... need help!!
Visit this link. Copy your json response and paste in the json section. Give your class name and hit Generate Dart.
Now hit copy dart code and add it your project. Then you can use it like inside the success case.
Note if you face any error of Null object. Thats mean your response contains null values and replace this data type with the corresponding data type.
if(response.statusCode == 200){
print('2');
YourJsonResponse obj = YourJsonResponse.fromJson(jsonDecode(response.body));
} else{
print("3");
print(response.statusCode);
}

How can I invoke and use Google Cloud Functions in a Flutter app?

I have created a url scraper function, working and tested on Google Cloud, but I am really drawing a blank on how to invoke it. I have tried two methods, one using the cloud_functions package, and the other using a standard HTTPS get. I've tried looking online, but none of the solutions/guides involve functions with an input from the Flutter app, and an output back to the app.
Here's the structure of the function (which is working alright). I've named this function Parse in Google Cloud Platform.
<PYTHON PACKAGE IMPORTS>
def Parser(url):
<URL PARSE FUNCTIONS>
return source, datetime, imageurl, keyword
def invoke_parse(request):
request_json = request.get_json(silent=True)
file = Parser(request_json['url'])
return jsonify({
"source": file[0],
"datetime": file[1],
"imageurl": file[2],
"keyword": file[3],
})
The first method I tried was using an HTTP CALL to get the function. But that isn't working, even though there are no errors - I suspect it's just returning nothing.
parser(String url) async{ // Here I honestly don't know where to use the url input within the function
var uri = Uri.parse(<Function URL String>);
HttpClient client;
try {
var request = await client.getUrl(uri);
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
var json = await response.transform(utf8.decoder).join();
Map data = jsonDecode(json) as Map;
source = data['source']; // These are the variables used in the main Flutter app
postedAt = data['datetime'];
_imageUrl = data['image'];
keyword = data['keyword'];
} else {
print('Error running parse:\nHttp status ${response.statusCode}');
}
} catch (exception) {
print('Failed invoking the parse function.');
}
}
That didn't work, so I thought I might alternatively use the cloud_functions package as follows (in lieu of the previous):
parser(String url) async {
var functionUrl = <FUNCTION URL>;
HttpsCallable callable = CloudFunctions.instance.getHttpsCallable(functionName: 'Parse')
..timeout = const Duration(seconds: 30);
try {
final HttpsCallableResult result = await callable.call(
<String, dynamic>{
'url': url,
}
);
setState(() {
source = result.data['source']; //THESE ARE VARIABLES USED IN THE FLUTTER APP
postedAt = result.data['datetime'];
_imageUrl = result.data['image'];
keyword = result.data['keyword'];
});
}
on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
} catch (e) {
print('caught generic exception');
print(e);
}
}
In the latter case, the code ran without errors but doesn't work. My flutter log states the following error:
I/flutter ( 2821): caught generic exception
I/flutter ( 2821): PlatformException(functionsError, Cloud function failed with exception., {code: NOT_FOUND, details: null, message: NOT_FOUND})
which I'm assuming is also an error at not being able to read the function.
Any help on how I should go about processing my function would be appreciated. Apologies if something is a really obvious solution, but I am not familiar as much with HTTP requests and cloud platforms.
Thanks and cheers.
Node Js Backend Function
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.test = functions.https.onCall(async (data, context) => {
functions.logger.info("Hello logs: ", {structuredData: true});
functions.logger.info( data.token, {structuredData: true});
}
Flutter frontend
1- pubspec.yaml
cloud_functions: ^1.1.2
2 - Code
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('test');
final HttpsCallableResult results = await callable.call<Map>( {
'token': token,
});