Post List of Data to API in flutter - 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)

Related

How to get the value of a key from json in 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
}

How to send a scheduled FCM message using the event_time parameter of the FCM Post API? [duplicate]

This question already has answers here:
FCM Schedule delivery date or time of push notification
(2 answers)
How can scheduled Firebase Cloud Messaging notifications be made outside of the Firebase Console?
(2 answers)
Closed 9 months ago.
I want to send a scheduled push notification using firebase messaging from my flutter app.
I use the below code to send a push notification from my app, which works without any issues:
Future<bool> callOnFcmApiSendPushNotifications(String title, String body, List<dynamic> receivers, {String? image = "", String screen = ''}) async {
print('normal message');
List<dynamic> tokens = await pushNotificationsManager.getTokens(receivers);
final postUrl = 'https://fcm.googleapis.com/fcm/send';
Map<String, dynamic> data;
data = {
"registration_ids" : tokens,
"collapse_key" : "type_a",
"notification" : {
"title": title,
"body" : body,
"sound": "default",
"click_action": "FLUTTER_NOTIFICATION_CLICK",
},
'data':{
"title": title,
"body": body,
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"screen": screen,
},
};
final headers = {
'content-type': 'application/json',
'Authorization': authKey
};
final response = await http.post(Uri.parse(postUrl),
body: json.encode(data),
encoding: Encoding.getByName('utf-8'),
headers: headers);
if (response.statusCode == 200) {
return true;
} else {
print(' FCM error');
return false;
}
}
Now for some notifications, I want to send them at 11AM the next day, which I tried to implement using the event_time parameter of the API as per the code below. However, when I try this code, the notification arrives immediately at the receiver, without the required delay.
Future<bool> callOnFcmApiSendDelayedPushNotifications(String title, String body, List<dynamic> receivers, {String? image = "", String screen = ''}) async {
List<dynamic> tokens = await pushNotificationsManager.getTokens(receivers);
// set time to 11AM next day
DateTime dt = DateTime.now();
DateTime dtTomorrow = DateTime(dt.year, dt.month, dt.day+1, 11);
final postUrl = 'https://fcm.googleapis.com/fcm/send';
Map<String, dynamic> data;
data = {
"registration_ids" : tokens,
"collapse_key" : "type_a",
"notification" : {
"title": title,
"body" : body,
"event_time": Timestamp.fromDate(dtTomorrow).millisecondsSinceEpoch.toString(),
"sound": "default",
"click_action": "FLUTTER_NOTIFICATION_CLICK",
},
'data':{
"title": title,
"body": body,
"event_time": Timestamp.fromDate(dtTomorrow).millisecondsSinceEpoch.toString(),
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"screen": screen,
},
};
final headers = {
'content-type': 'application/json',
'Authorization': authKey
};
final response = await http.post(Uri.parse(postUrl),
body: json.encode(data),
encoding: Encoding.getByName('utf-8'),
headers: headers);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
I know it is possible to send scheduled push notifications from the Firebase console, but is there any way to send a scheduled notification from the app? Note that I am on a free spark plan so cloud functions cannot be used.
Thanks in advance!

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);
}

send image and text at the same time flutter

I want to upload image and other types of data like string and integer with the HTTP post method at the same time. but i got error code said that json cant encode image file, i have this code on flutter :
static Future<ApiReturnValue<Asset>> addAsset(Asset asset, File imageFile,
{http.Client client}) async {
client ??= http.Client();
String url = baseUrl + 'asset';
var uri = Uri.parse(url);
var response = await client.post(
uri,
headers: {
"Content-type": "application/json",
"Authorization": "Bearer ${User.token}"
},
body: jsonEncode(
<String, dynamic>{
"name": asset.name,
"condition": asset.condition,
"purchase_date": asset.purchaseDate,
"price": asset.price,
"location": asset.location,
"description": asset.description,
"image": imageFile,
},
),
);
if (response.statusCode != 200) {
return ApiReturnValue(message: "Add item failed, please try again");
}
var data = jsonDecode(response.body);
Asset value = Asset.fromJson(data['data']['asset']);
return ApiReturnValue(value: value);
}
is that any way that I can send image and text on HTTP post request at the same time without separating the image using multipart request?
To include an image in the request body for POST, normally you have to convert it into a multipart file, then include it in the body as formdata. This required the server to expect the multipart file within the formdata itself when receive the image from client.
I'd like to recommend this package name dio for you. It supports MultipartFile, FormData and other powerful helper classes.
Here's an example:
static Future<bool> sendImage(String imagePath) async {
try {
final content = MultipartFile.fromFile(imagePath);
final contentType = 'multipart/form-data';
final Response response = await dio.post('$BASE_URL/$images',
data: FormData.fromMap({'file': content}),
options: Options(contentType: contentType));
if (response.statusCode == 200) {
return true;
}
return false;
} catch (error) {
return null;
}
}
You can read more on the FormData here
You can have your asset data in the request header:
var response = await client.post(
uri,
headers: {
"Content-type": "application/json",
"Authorization": "Bearer ${User.token}",
"asset-data": jsonEncode(
<String, dynamic>{
"name": asset.name,
"condition": asset.condition,
"purchase_date": asset.purchaseDate,
"price": asset.price,
"location": asset.location,
"description": asset.description
},
),
},
body: imageFile.readAsBytesSync(),
);
This will need you to modify your server-side code to read from the header.

fetch data from an API with the use of ID in flutter

I work on a delivery man application and I need to have from an API the details of an order received on the account of a delivery man.
here is an example:
{
"Status": "1",
"Order": {
"deliveryCost": "5.000",
"amount": "38.400",
"total": "43,400",
"hors_remise": "34.560",
"Dishes": [
{
"cartID": "00000",
"dishID": "13548",
"dimensionID": 0,
"title": "Classic 16 pieces trays:",
"ingredient": "10 piece trays + 2 gunkan + 4 shrimp crunchy",
"price": "38.400",
"quantity": "1",
"imagePath": "https://www.monresto.net/test/plats/P_170121112803.jpg",
"Options": []
}
],
and to access of all this information I must specify the "KEY" I had on the postan
my question is how can i add (orderID)?
there is my code :
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
class datePageClass extends StatefulWidget {
#override
_datePageClassState createState() => _datePageClassState();
}
class _datePageClassState extends State<datePageClass> {
void getData() async {
http.Response response = await http.post(
'https://api/ws/v3/Delivery/orderDetails.php');
if (respo
nse.statusCode == 200) {
String data = response.body;
var cmddetails = jsonDecode(data);
print(cmddetails);
} else {
print(response.statusCode);
}
print('');
}
#override
Widget build(BuildContext context) {
getData();
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
),
);
}
}
Did you try this?
var response = await http.post('https://www.apiurl.com/ws/v2/details.php', body: {'OrderID': 1209, 'OtherParam': 'value'});
Then in PHP
$OrderID = $_POST["OrderID"];
$OtherParam = $_POST["OtherParam"];
Make sure to sanitize the variables to avoid SQL Injections
And then you can send JSON back to dart/flutter.
Pre-check: Are your sure that this URL expects http-POST not http-GET?
You want to add orderID to the request, right?
If that's the case, first you need to find if API expects this parameter as query parameter or part of the body.
Nevertheless, here are examples for both cases.
String orderDetailsUrl = 'https://www.monresto.net/ws/v3/Delivery/orderDetails.php';
orderID as query parameter:
orderDetailsUrl += "?orderID=FIXME_ORDER_ID";
http.Response response = await http.post(orderDetailsUrl);
orderID as part of request body:
Map<String, dynamic> data = Map()
..putIfAbsent("orderID", () => "FIXME_ORDER_ID")
var body = jsonEncode(data);
http.Response response = await http.post(orderDetailsUrl, headers: {"Content-Type": "application/json"}, body: body);