How to get the value of a key from json in flutter? - flutter

In my API I need to get the value from the "value" key of the readm pair.
"extra_info": [
{
"name": "readme",
"value": "**In this session, we will work on different activities using Toggle Board:**\nIdentify animals using characteristics\nRecognize the animals by listening to a song"
},
{
"name": "skill",
"value": "Play school"
},
{
"name": "sub_skill",
"value": "Toggle board"
}
],
I tried using like this but some case the index number will change.
hotsLevelController.other_list[0].extraInfo[0].value;

Probably you have a json response which is come from HTTP request.
so this can help you:
final response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
List<dynamic> itemsList = jsonResponse['extra_info'] as List<dynamic>;
// print values
for (var item in itemsList) {
print((item as Map<String, String>)['value']);
}
}

Basic JSON serialization in Flutter is very simple. Flutter has a built-in dart:convert library that includes a straightforward JSON encoder and decoder.
You can learn from here: https://docs.flutter.dev/development/data-and-backend/json
or you can use this function:
// findKey will me 'readme' in your case
// pass the json data iin json
findValue(dynamic json, String findKey) {
final data = json.decode(json) as Map<String, dynamic>;
List<Map<String, String>> items = data['extra_info'] as List<Map<String, String>>;
for (var item in items) {
if (item['name'] == findKey) {
return item['value'];
}
}
return null; //not found
}

Related

How can I store the values ​of the json or request in a variable without using future builder or list builder in flutter?

I want to use the information I get from the json or request and be able to use it in a useraccountheader drawer but WITHOUT, using a list builder or future builder.
I usually use a future builder and display the information from the database.
I want to get the json or request information and store it in a variable or use it directly in a text widget.
It is also to have loaded user information.
In the infoinitialuser2 list, the values ​​of the json or request are stored and I show them in the list builder or future builder, but as I just mentioned, I don't want to do it that way.
code::
Class State<NombreCabeceraDrawer> extends StatefulWidget{return nombrecabeceradrawer()}
class nombrecabeceradrawer extends State<NombreCabeceraDrawer> {
verride
void initState() {
cabeceradrawerservices.MostrarInfoInicialUser().then((value) {
setState(() {
info.addAll(value);
});
} );
super.initState();
}
UserAccountsDrawerHeader(
accountName: Text("here i want to show the value of the json or request"),
accountEmai: Text("here i want to show the value of the json or request too")
),
}
-------------------
class InfoUsuarioInicialServices{
Future MostrarInfoInicialUser() async{
Map<String, String> headers = {
'Content-Type':'application/json;charset=UTF-8',
'Charset':'utf-8'
};
var Url= Uri.parse("http://");
final response = await http.get((Url),headers: headers);
print(response.body);
return productInfoUsuarioInicialromJson(response.body);
}
}
---------------------
List productInfoUsuarioInicialromJson(String str) => List<InfoInicialUserModel>.from(json.decode(str).map((x) => InfoInicialUserModel.fromJson(x)));// con esto hago el get
class InfoInicialUserModel{
String UsuarioPk;
String FotoUsuario;
String CorreoUsuario;
String NombreUsuario;
InfoInicialUserModel({this.UsuarioPk,this.FotoUsuario,this.NombreUsuario,this.CorreoUsuario});
factory InfoInicialUserModel.fromJson(Map<String, dynamic> parsedJson){
return InfoInicialUserModel(
UsuarioPk: parsedJson['Usuari'],
FotoUsuario:parsedJson['image'],
NombreUsuario: parsedJson['Usuario_A'],
CorreoUsuario:parsedJson['Usuario_C']
);
}
}
This is how I would do it:
Future GetMostrarInfoInicialUser() async {
Map<String, String> headers = {
'Content-Type': 'application/json;charset=UTF-8',
'Charset': 'utf-8'
};
var Url = Uri.parse("http://");
final response = await http.get((Url), headers: headers);
if (response.statusCode == 200) {
print(response.body);
var jsonData = json.decode(response.body);
if (jsonData == "Error") {
} else {
if (mounted) {
setState(() {
accountEmail = jsonData['accountEmail'];
accountName = jsonData['accountName'];
});
}
}
}
}
#override
void initState() {
GetMostrarInfoInicialUser();
}

flutter How to check the size of a growable list growable list

I have a scenario, I have a login page on my app when a user logins in, the app waits for a response from the api, the api response can come in 2 ways. On way with the data as empty or with a growable list. Eg
{
"id": "ea6d156a-ac2e-49b1-b006-1cf2c9092224",
"auth_token": "token",
"email": "tester#gmail.com",
"gender": male,
"fullname": "tester",
"contactNo": "08056582232",
"participants": [
{
"participantid": "055556666",
"dateobirth": "1983-10-12T00:00:00",
"nextofkinname": "Tester",
"nextofkinemail": "tester#gmail.com",
"nextofkinphonenumber": "1234567",
"gender": "female",
"contactnumber": "8900000",
"fullname": "Participant Two",
"userid": "ea6d156a-ac2e-49b1-b006-1cf2c9092224",
"schedules": [
{
"id": 74436,
"followUpStageId": 1,
"windowStart": "2022-01-28T00:00:00",
"windowEnd": "2022-01-30T00:00:00",
"showUp": 0,
"showUpDate": null,
"vaxDose": 0,
}
]
}
or it can come as
{
"id": "afc7e6ff-878a-418b-9a2f-6f7fe2240085",
"auth_token": "",
"email": "tester#gmail.com",
"gender": "male",
"fullname": "tester",
"contactNo": "1234567",
"participants": []
}
Am storing the values in a shared preference, and using them in different places in the app.
I want to check if participants: [] had data if it has data take the user directly to the home screen if is empty the go through the process of adding a participant. How can I check if the size of the participant is zero or not?
this is what I have so far
void getLoggedInStatus() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
isLoggedIn = prefs.getBool('isLoggedIn') ?? false;
gotData = prefs.getString("participants") ??[]; // get the data from prefs
print(gotData);
double data = jsonDecode(gotData);// decode and get size
print(data);
var token = prefs.get("auth_token") ?? "";
var url = Uri.parse(Api.PARTICIPANT_SCHEDULER);
debugPrint("user is logged in: $isLoggedIn");
if (isLoggedIn) {
try {
// try accessing anything from the server
var response = await http.get(url,
headers: {"authorization": "Bearer $token"});
// token expiration check
// if 401 is not returned, the token is still valid. skip authentication
if (response.statusCode != 401) {
if (data.size !=0) { //this doesnt work, it skips the if statements and does nothing
WADashboardScreen().launch(context); //go to home screen if not empty
} else {
WAAddCredentialScreen().launch(context); //add user details if it is empty
}
}
} on SocketException catch (_) {}
}
}
How am saving to the shared prefs
SharedPreferences prefs = await SharedPreferences.getInstance();
var parse = jsonDecode(response.body);
prefs.setBool("isLoggedIn", true);
await prefs.setString('email', parse["email"]);
await prefs.setString('auth_token', parse["auth_token"]);
await prefs.setString('gender', parse["gender"]);
await prefs.setString('participants', (jsonEncode(parse["participants"]))) ;
await prefs.setString('fullname', parse["fullname"]);
await prefs.setString('id', parse["id"]);
Have been scratching my head for a while now, how can I check the size or check if participants has data or not and then proceed to the different screens? Any help is appreciated
In
await prefs.setString('participants', (jsonEncode(parse["participants"])));
You are doing two wrong things here.
You are encoding & parsing json which you are supposed itself a String?
You are storing List<dynamic> as a String which is not the optimal way.
You might want to use other packages to store participants. SharedPreference is not optimal for every use case.
var body=json.decode(response.body);
if(body["participants"].isEmpty){
...
}
should help you...

Ways of making my flutter app faster at fetching from api

I am wondering if there are faster ways of doing this fetch, the for loop currently takes approx 10s but it's waiting for each fetch to finish before starting on the next one I also tried a forEach loop but then I had issues with the responses array being empty. Is there any smart Dart way of fetching it faster then returning the array to flamingotest
Here is my code!
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../classes/flamingo_test.dart';
import '../classes/convert_wallet.dart' as walletfunc;
import 'package:flutter_settings_screens/flutter_settings_screens.dart';
import '../utilities/assets.dart' as assets; // Object of assets
Future<FlamingoTest> fetchPost() async {
String apiUrl = "xxxxxx";
var responses = [];
for (var mapEntry in assets.assets.entries) {
var wallet = Settings.getValue<String>("user-wallet", "");
print(wallet);
var userWalletSeed = walletfunc.convertWallet(wallet);
print(userWalletSeed);
var body = json.encode({
"jsonrpc": "2.0",
"method": "invokefunction",
"params": [
"4d92194e8d73980dadbadfc1993b2014c9fbd9da",
"checkFLM",
[
{"type": "Hash160", "value": userWalletSeed},
{"type": "Hash160", "value": mapEntry.value}
]
],
"id": 3
});
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
var response =
await http.post(Uri.parse(apiUrl), body: body, headers: headers);
print(response);
if (response.statusCode == 200) {
print(response);
var uncoded = jsonDecode(response.body);
responses.add(uncoded);
} else {
throw Exception('Failed to load post');
}
}
return new FlamingoTest.fromJson(responses);
}
You can use Future.wait like this. The map will return a Iterable of Future<Response> and perform the post simultaneously.
Future<Response> fetchResponse(var mapEntryValue) async {
//The code in your for-loop goes here
...
return response;
}
Future<FlamingoTest> fetchPost() async {
var responses = [];
await Future.wait(
assets.assets.entries
.map<Future<Response>>(
(MapEntry me) => fetchResponse(me.value),
)
.toList(),
).then((listOfResponses) {
responses.addAll(listOfResponses);
});
return new FlamingoTest.fromJson(responses);
}

How to solve this List<dynamic> type error in Flutter/Dart

I am very new to flutter and dart. Trying to return a list from this future that pulls data from an api but I keep getting this error. Someone here helped me solve a similar error by casting to a list because I was calling map function on an array that returns an iterable but in this case here I'm not sure what needs to be done.
type List<dynamic> is not a subtype of type FutrueOr<ListCity>>
Data is received like below:
{
"data": {
"127287": {
"Feature_int_id": "127287",
"Admin1_str_code": "US06",
"Country_str_code": "US",
"Feature_str_name": "Acampo",
"Feature_dec_lat": "38.194",
"Feature_dec_lon": "-121.25"
},
"116496": {
"Feature_int_id": "116496",
"Admin1_str_code": "US06",
"Country_str_code": "US",
"Feature_str_name": "Acton",
"Feature_dec_lat": "34.49",
"Feature_dec_lon": "-118.22"
},
"124284": {
"Feature_int_id": "124284",
"Admin1_str_code": "US06",
"Country_str_code": "US",
"Feature_str_name": "Adelanto",
"Feature_dec_lat": "34.665",
"Feature_dec_lon": "-117.512"
},
}
Below is the code for future:
Future<List<City>> fetchCitiesByProvince(provinceCode) async {
final response = await http.get(Uri.https('localhost/msd', 'api/cities/' + provinceCode));
final responseJson = json.decode(response.body);
final dataMap = responseJson['data'];
if (response.statusCode == 200) {
List citiesList = [];
for (var city in dataMap.keys) {
if (dataMap[city]['Admin1_str_code'] == provinceCode) {
citiesList.add(
{
'cityCode': dataMap[city]['Feature_int_id'],
'cityName': dataMap[city]['Feature_str_name']
}
);
}
}
return citiesList;
} else {
throw Exception('Failed to load cities');
}
}
City Class:
class City {
final String cityCode;
final String cityName;
City({#required this.cityCode, #required this.cityName});
factory City.fromJson(Map<String, dynamic> json) {
return City(
cityCode: json['Feature_int_id'],
cityName: json['Feature_str_name']
);
}
}
You need to return List<City> in your method. So, change the following code:
List citiesList = [];
to
List<City> citiesList = [];
--- UPDATE ---
You need to user your City constructor or factory to generate the item from json like this:
City.fromJson(dataMap[city]);
// Or
City(cityCode: dataMap[city]['Feature_int_id'],
cityName: dataMap[city]['Feature_str_name']
);
Here the updated sample code:
Future<List<City>> fetchCitiesByProvince(provinceCode) async {
final response = await http.get(Uri.https('localhost/msd', 'api/cities/' + provinceCode));
final responseJson = json.decode(response.body);
final dataMap = responseJson['data'];
List<City> citiesList = [];
if (response.statusCode == 200) {
for (var city in dataMap.keys) {
if (dataMap[city]['Admin1_str_code'] == provinceCode) {
citiesList.add(City.fromJson(dataMap[city]));
}
}
} else {
throw Exception('Failed to load cities');
// either throwing an error or return empty list.
}
return citiesList;
}

Post List of Data to API in flutter

I am currently working on an API and I want to post a list of data to the API.
this is an e-commerce example, so I would need to pass the multiple items in the cart as per the line no, line no will auto-increment. and order should be posted with the same order ID but with a different order number.
This is what the Json looks like -
{
"VarFID": 1,
"VarCID": 1,
"VarAreaCode": 1,
"VarAge": 250,
"VarB": 20,
"VarF": 1,
"VarC": 256,
"VarF": 1,
"OrderLines": [
{
"OrderID": "SQ/19/10",
"Line No_": 1,
"Date": "2019-04-02 00:00:00",
"Time": "2019-04-02 11:38:48",
"No_": "FAG-033",
"Name": "LC GOLD",
"Quantity":000,
"Unit Price": 10000,
"Amount": 10000,
"Status": "Under Processing",
"Remarks": "VIKRAM",
"VariantCode":3
},
{
"OrderID": "SQ/19/10",
"Line No_": 2,
"Date": "2019-04-02 00:00:00",
"Time": "2019-04-02 11:38:48",
"No_": "F061",
"Name": "LC S - I",
"Quantity": 00,
"Unit Price": 100,
"Amount": 300,
"Status": "Under Processing",
"Remarks": "VIKRAM ",
"VariantCode":2
}
]
}
This is the code I am using to generate the array, the data is going through, but it is only posting one item/line and not both of them.
void sendData2() async {
mainModel = MainModel(
VarFID: "1",
VarCID: "1",
VarAreaCode: "1",
VarAge: "1",
VarB: "1",
VarF: "1",
VarC: "1",
VarF: "1",
OrderLines: listOrderLines.OrderLines);
var response = await http.post(
Uri.https('softwareonus.com:8082', '/admindealerlist/'),
headers: {"Content-Type": "application/json"},
body: json.encode(mainModel.toJson()),
);
print(" Send Data 2 Response : ${response.body}");
print(" Send Data 2 Response : ${response.statusCode}");
}
I have created model classes using JsonSerialazble
You are doing body: json.encode(mainModel.toJson()), which is pointless since your function .toJson() in your model already does the json.encode(..) for you. You should just .post your mainModel.toJson() to your API.
Based on the data, you have shared. Create 2 Model Classes-
Object Model Class of each object you have
Super Model class (use Object Model Class here like the code)
code Snippet:
ObjectModel-:
import 'package:json_annotation/json_annotation.dart';
part 'ObjectModel.g.dart'; // you have to use naming convention of like this (yourfilename.g.dart)
#JsonSerializable()
class ObjectModel
{
String orderId;
String lineNo;
//All other variable define here
// Initilize all in the constructor
ObjectModel({this.orderId,this.lineNo,[.... your othersVariable...]});
#override
factory ObjectModel.fromJson(Map<String, dynamic> json) =>
_$ObjectModelFromJson(json);
Map<String, dynamic> toJson() => _$ObjectModelToJson(this);
}
SuperModel:
import 'package:json_annotation/json_annotation.dart';
part 'SuperModel.g.dart'; ///you have to use naming convention of like this (yourfilename.g.dart)
#JsonSerializable()
class SuperModel {
String varFid;
String varCID;
// alll othervarialble...
List<ObjectModel> orderLines;
//initilize all in constructor
SuperModel({ this.varFid,this.varCID ,[.....otherVariable],this.orderLines });
factory SuperModel.fromJson(Map<String, dynamic> json) =>
_$SuperModelFromJson(json);
Map<String, dynamic> toJson() => _$SuperModelToJson(this);
}
Note: To create Model Classes I am using this two packages and I have put that in dev_dependency:
dev_dependencies:
flutter_test:
sdk: flutter
build_runner:
json_serializable: ^3.3.0
Now you have to run the below command to generate the g.dart file
flutter pub run build_runner build
Now finally you can do HTTP Post request and model class like this-
void send() async {
\\SuperModel supermodel = SuperModel ([initialize data to this model class])
var response = await http.post(
Uri.https('softwareonus.com:8082', '/admindealerlist/'),
headers: {"Content-type": "application/json"},
body: json.encode(supermodel .toJson()));
print(response.body);
}
}
Alternatively you can watch my Model Class series on Youtube Here is the link: https://youtube.com/playlist?list=PLtIU0BH0pkKpXE-1vC7NswofFPby1OYh-
Thanks :)
Update:
Suppose there is a button in your app, when you click on the button then you add the data on the list
class _ListDataState extends State<ListData> {
SuperModel superModel = SuperModel ();
#override
Widget build(BuildContext context) {
// your UI code
}
void add() {
setState(() {
superModel.orderLines.add(ObjectModel(Your all variable initialize here);
});
}
Call this add method whenever you wanted to add new order in your list. After adding all data send it using send method
void send() async {
var response = await http.post(
Uri.https('softwareonus.com:8082', '/admindealerlist/'),
headers: {"Content-type": "application/json"},
body: json.encode(supermodel .toJson()));
print(response.body);
}
Replace with your object class, which must have the toJson() method that returns the Map.
import 'dart:convert' on to your API function class
And don't forget to add,
headers: {'Content-type': 'application/json','Accept': application/json'},
Future<bool> addToSaleDetail(List<YourCustomObject> _listOfObject) async {
String unparsedUrl = "$baseUrl/AddMobileListSaleBrief";
var url = Uri.parse(unparsedUrl);
List jsonList = [];
_listOfObject.map((item) => jsonList.add(item.toJson())).toList();
final response = await http.post(
url,
body: json.encode({"finalResponse": jsonList}["finalResponse"]),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json'
},
);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Try to change your mainModel to Map<String, dynamic> then encode your Map<String, dynamic> to json and send it to body. Add this 'Content-type': 'application/json' to your headers to make your request sent as json. For Example :
List<Map<String, String>> listItem = <Map<String, String>>[];
for (var element in myList) {
Map<String, String> val = {
'product': element.product.id_product.toString(),
'quantity': element.quantity.toString(),
'total': element.total.toString(),
};
listItem.add(val);
}
Map data = {
'pay': pay,
'customer': id_customer.toString(),
'items': listItem, // this is a List
};
final http.Response response = await client.post(
Uri.parse(...), // your url
headers: {
'content-type': 'application/json' // don't forget this one
},
body: jsonEncode(data), // encode my Map to json
);
That's it! (by the way this is example of my code)