Api Call With Nested Map Flutter - json

I am trying to make a POST call to my server that requires my data to be shaped like this:
{
"dispensary": 1,
"order_detail": [
{"product_size": 1,
"quantity": 1}
]
}
But when I make my api call, I get a 500 error on my back end saying the data looks like this:
{'{"dispensary":1,"order_detail":{"product_size":1,"quantity":1}}': ['']}
I am making the call like this:
Future getdata(dispensary, order) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
var token = prefs.getString('token');
var url = '$server/api/customer/order/getdata/?access_token=$token';
Map<String, dynamic> orderRating = {
'dispensary': dispensary,
'order_detail': order
};
await http.post(url, body: orderRating, headers: {
"Content-Type": "application/x-www-form-urlencoded"
}).then((http.Response response) {
switch (response.statusCode) {
case (200):
var responseData = json.decode(response.body);
Rate rateData =
Rate.fromJson((responseData[1]['rate_response']['rates']));
print('uploaded successfully');
print(rateData.carrierId);
break;
case (400):
print('Bad Data');
break;
case (500):
print('Failed Upload');
isUploaded = false;
break;
default:
print('Unable to get rates');
}
});
print('uploaded successfully');
}
With order_detail being a map itself of {"product_size": 1,
"quantity": 1}.
I cannot complete the call to my server. Could you tell me what I'm doing wrong

I don't get exactly what are you doing, because it's not the whole future function in it ... but I can make a guess you're trying to make a post request, where the body have some dynamic data.
What are you doing right now as far as I can see is that you're putting a map inside a map which is not what you want.
My suggestion is something like this:
Future<http.Response> postSomething(int dispensary, List<Map<String,dynamic>> order) async {
final String url = 'yoururl';
final Map<String, dynamic> body = {
'dispensary': dispensary,
'order_detail': order
};
final request = await http.post(url: url, body: convert.jsonEncode(body));
if(request.statusCode == 200) {
return something
} else {
throw Exception('Failed to send the request!!!')
}
}
Hope that my answer will help you and give a clearer idea. :)

Add the toJson methods to your objects. call toJson when generating your requests body
body: orderRating.toJson
should return the json structure as seen in this snippet
{
"dispensary": 1,
"order_detail": [
{"product_size": 1,
"quantity": 1}
]
}
class OrderRating{
int dispensary;
List<OrderDetail> orderDetail;
OrderRating({this.dispensary, this.orderDetail});
OrderRating.fromJson(Map<String, dynamic> json) {
dispensary = json['dispensary'];
if (json['order_detail'] != null) {
orderDetail = new List<OrderDetail>();
json['order_detail'].forEach((v) {
orderDetail.add(new OrderDetail.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['dispensary'] = this.dispensary;
if (this.orderDetail != null) {
data['order_detail'] = this.orderDetail.map((v) => v.toJson()).toList();
}
return data;
}
}
class OrderDetail {
int productSize;
int quantity;
OrderDetail({this.productSize, this.quantity});
OrderDetail.fromJson(Map<String, dynamic> json) {
productSize = json['product_size'];
quantity = json['quantity'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['product_size'] = this.productSize;
data['quantity'] = this.quantity;
return data;
}
}
The above code was generated using a tool found Here

Related

How to Create Model for Nested JSON where There is a List of JSON Inside Nested JSON?

I have a structure of JSON response like code below (example):
{
"data": {
"items": [
{
"id": 1,
"name": "Baburiki",
"jutsu_variant": [
{
"jutsu_name": "wind release",
"damage": 1200,
},
],
},
{
"id": 2,
"name": "Zee",
"jutsu_variant": [
{
"jutsu_name": "wind release",
"damage": 1200,
},
{
"jutsu_name": "kage bunshin",
"damage": 2000,
},
],
},
],
},
}
There is a list of JSON on the items key and in that key, there is another list of JSON on the jutsu_variant key.
I have created a class model to store the JSON response like the following code
class ShinobiData {
int? id;
String? shinobiName;
JutsuVariant? jutsuVariant;
ShinobiData({
this.id,
this.shinobiName,
this.jutsuVariant,
});
factory ShinobiData.fromJson(Map<String, dynamic> json) {
return ShinobiData(
id: json['id'],
shinobiName: json['name'],
jutsuVariant: json['jutsu_variant'],
);
}
}
class JutsuVariant {
String? jutsuName;
int? jutsuDamage;
JutsuVariant({this.jutsuName, this.jutsuDamage});
factory JutsuVariant.fromJson(Map<String, dynamic> json) {
return JutsuVariant(
jutsuName: json['jutsu_name'],
jutsuDamage: json['damage'],
);
}
}
The model is working fine if there is no list on the jutsu_variant key.
This is my class for getting the API response of POST requests. (created with provider state management)
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:learning_api/model/shinobi_model.dart';
class CatalogResponse with ChangeNotifier {
Map<String, dynamic> _map = {};
bool _error = false;
String _errorMessage = '';
List<ShinobiData> _shinobis = [];
Map<String, dynamic> get map => _map;
List<ShinobiData> get shinobis => _shinobis;
bool get error => _error;
String get errorMessage => _errorMessage;
Future<void> get fetchData async {
var _finalBody = {
'page': 1,
'items_per_page': 5,
};
String _body = const JsonEncoder().convert(_finalBody);
final response = await http.post(
Uri.parse('https://***/url'),
body: _body,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
);
if (response.statusCode == 200) {
try {
_map = (jsonDecode(response.body))['data'];
List<dynamic> _listShinobi = (_map)['items'];
// this loop will add each item in the items key
for (int i = 0; i < _listShinobi.length; i++)
_shinobis.add(CatalogData.fromJson(_listItem[i]));
_error = false;
} catch (e) {
_error = true;
_errorMessage = e.toString();
_map = {};
_catalogs = [];
}
} else {
_error = true;
_errorMessage = "Error: It would be your internet connection";
_map = {};
_catalogs = [];
}
notifyListeners();
}
void initialValues() {
_map = {};
_catalogs = [];
_error = false;
_errorMessage = "";
notifyListeners();
}
}
The above code works perfectly for name and id key calling. But the problem occurs when calling the jutsu_variant key. What should I do to be able to call the value of the jutsu_name and the damage key that is in the jutsu_variant key?
Cases like this do not exist in any tutorial resources. Maybe your answer will be very valuable in the future. Thank you in advance
in your ShinobiData class
you should use List<JutsuVariant> instead of JutsuVariant
you can use json_serializable or even freezed to generate these files automatically for you
This IDE plugin JosnToDart is very convenience for me. It can generate response model just paste json to this. More we can choose nullable or not option when generate.

flutter foreach loop on json response from API

I have converted my JSON response in the below model:
VehicleList vehicleListFromJson(String str) =>
VehicleList.fromJson(json.decode(str));
String vehicleListToJson(VehicleList data) => json.encode(data.toJson());
class VehicleList {
VehicleList({
this.vehicles,
});
List<Vehicle> vehicles;
factory VehicleList.fromJson(Map<String, dynamic> json) => VehicleList(
vehicles: List<Vehicle>.from(
json["vehicles"].map((x) => Vehicle.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"vehicles": List<dynamic>.from(vehicles.map((x) => x.toJson())),
};
}
class Vehicle {
Vehicle({
this.vehid,
this.vehname,
this.vehdescrip,
this.vehbodyopen,
this.vehbodyopenimg,
this.vehbodyclose,
this.vehbodycloseimg,
});
String vehid;
String vehname;
String vehdescrip;
String vehbodyopen;
String vehbodyopenimg;
String vehbodyclose;
String vehbodycloseimg;
factory Vehicle.fromJson(Map<String, dynamic> json) => Vehicle(
vehid: json["vehid"],
vehname: json["vehname"],
vehdescrip: json["vehdescrip"],
vehbodyopen: json["vehbodyopen"],
vehbodyopenimg: json["vehbodyopenimg"],
vehbodyclose: json["vehbodyclose"],
vehbodycloseimg: json["vehbodycloseimg"],
);
Map<String, dynamic> toJson() => {
"vehid": vehid,
"vehname": vehname,
"vehdescrip": vehdescrip,
"vehbodyopen": vehbodyopen,
"vehbodyopenimg": vehbodyopenimg,
"vehbodyclose": vehbodyclose,
"vehbodycloseimg": vehbodycloseimg,
};
}
I make the API call like this:
Future<VehicleList> getVehicles() async {
var client = http.Client();
var vehicleModel = null;
try {
var response = await client.get(Uri.parse(Strings.getVehiclesUrl));
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
vehicleModel = VehicleList.fromJson(jsonMap);
}
} catch (Exception) {
return vehicleModel;
}
return vehicleModel;
}
Now I need to implement a for each loop on this to check if the value for key "vehbodyopen" is "Y" or "N" and create seperate arrays or objects for them and then display them in a ListViewBuilder widget.
Im new to flutter. Im from javascript background. I solved the problem in javascript by executing for each loop in the json response and stored them in two different arrays. Im looking for the same solution in flutter and dart if possible.
for (int i = 0; i < vehicleModel.length; i++) {
if(vehicleModel[i].vehbodyopen == "Y"){
//do stuff
}else{
//do another stuff
}
}
you might try this
I found a possible solution I had to loop over the vehicles List inside the vehicleModel.
List vehList = vehicleModel.vehicles;
List openVehList = [];
List closedVehList = [];
for (var veh in vehList) {
print('executing foreach');
if (veh.vehbodyopen == "Y") {
openVehList.add(veh);
} else {
closedVehList.add(veh);
}
}

Flutter : How to parse JSON Array of objects

Can anyone tell me how to parse arrays of object in flutter. When I am parsing the json I am getting error as List is not a subtype of type Map<String, dynamic>.
Below is my json file which needs to be parsed. Please help me to fix this issue.
[
{
"empPayslipsId": "2021012000440",
"month": "Jan",
"description": "Payslip for JAN 2021 (Month End)",
"paymentPeriod": "1/1/2021 12:00:00 AM - 1/31/2021 12:00:00 AM",
"lastAccessBy": "0002\r\n118.200.199.70",
"lastAccessDate": "20210202",
"lastAccessTime": "105706",
"successAccess": "2",
"failAccess": "2"
}
]
Future<void> loadQueryPeriod(int year, var month) async {
String baseURL = '${domainURL}api/PaySlip?year=$year&month=$month';
try {
final response = await http.get(baseURL, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization':
'Bearer ${Provider.of<UserVM>(navigatorKey.currentContext, listen: false).accessToken}',
});
print('UIC PDF response : ${response.body}');
print(
'UIC Token response : ${Provider.of<UserVM>(navigatorKey.currentContext, listen: false).accessToken}');
if (response.statusCode == 200) {
final Map<String, dynamic> data = json.decode(response.body);
print('result type: ${data.runtimeType}');
}
} catch (e) {
print(e);
throw Exception('Download PDF Fail! ${e.toString()}');
}
}
}
Change it to this:
final Map<String, dynamic> data = json.decode(response.body)[0];
This is because your map is inside a list. Look at the square brackets [ ] enclosing your map. The map that you need, is at index[0] of this list.
use this podo class :
// Generated by https://quicktype.io
// To parse this JSON data, do
//
// final sample = sampleFromJson(jsonString);
import 'dart:convert';
List<Sample> sampleFromJson(String str) {
final jsonData = json.decode(str);
return new List<Sample>.from(jsonData.map((x) => Sample.fromJson(x)));
}
String sampleToJson(List<Sample> data) {
final dyn = new List<dynamic>.from(data.map((x) => x.toJson()));
return json.encode(dyn);
}
class Sample {
String empPayslipsId;
String month;
String description;
String paymentPeriod;
String lastAccessBy;
String lastAccessDate;
String lastAccessTime;
String successAccess;
String failAccess;
Sample({
this.empPayslipsId,
this.month,
this.description,
this.paymentPeriod,
this.lastAccessBy,
this.lastAccessDate,
this.lastAccessTime,
this.successAccess,
this.failAccess,
});
factory Sample.fromJson(Map<String, dynamic> json) => new Sample(
empPayslipsId: json["empPayslipsId"],
month: json["month"],
description: json["description"],
paymentPeriod: json["paymentPeriod"],
lastAccessBy: json["lastAccessBy"],
lastAccessDate: json["lastAccessDate"],
lastAccessTime: json["lastAccessTime"],
successAccess: json["successAccess"],
failAccess: json["failAccess"],
);
Map<String, dynamic> toJson() => {
"empPayslipsId": empPayslipsId,
"month": month,
"description": description,
"paymentPeriod": paymentPeriod,
"lastAccessBy": lastAccessBy,
"lastAccessDate": lastAccessDate,
"lastAccessTime": lastAccessTime,
"successAccess": successAccess,
"failAccess": failAccess,
};
}
Now inorder to parse json call,
Sample sample = sampleFromJson(jsonString);
via this you will get the access to sample PODO class and you can access any object you want.
The initial data you received by calling a get request isn't stored in a map, but rather in a list.
You should do something like this to receive your initial data.
if (response.statusCode == 200) {
final List<dynamic> data = json.decode(response.body);
}
From there, they're numerous ways to get the data from your data variable. You can use lists here if you want, for example to get the value of month in the JSON.
final String month = data[0]['month'];
If you'd prefer to use Maps, the syntax it'll look like this
final Map<String, dynamic> endpointData = data[0];
final String responseKey = 'month';
final var result = endpointData[responseKey];
if you have data model you can do it like this
fromJsonList(List<dynamic> jsonList) {
List<YourModel> yourModelList = [];
jsonList.forEach((jsonModel) {
menuModelsOfferList.add(YourModel.fromJson(jsonModel));
});

How to concat two JSONObject with same key of a JSONArray in flutter

The JSON request has been split into two json object in the DataList JSONArray , because data is too large, how do i combine these two objects before i can decompress and get the values . Iam new to dart and flutter , any help would be appreciated. Thank you.
"DataList": [
{
"Data": "compressedata"
},
{
"Data": "compressedData"
}
],
here is what i have tried
class ResponseList {
List<DataList> dataList;
ResponseList({ this.DataList});
ResponseList.fromJson(Map<String, dynamic> json) {
if (json['DataList'] != null) {
DataList = new List<DataList>();
json['DataList'].forEach((v) {
dataList.add(new DataList.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> map = new Map<String, dynamic>();
if (this.DataList != null) {
map['DataList'] = this.dataList.map((v) => v.toJson()).toList();
}
return map;
}
}
class DataList {
String data;
DataList({this.data});
DataList.fromJson(Map<String, dynamic> json) {
data = json['Data'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> map = new Map<String, dynamic>();
map['Data'] = this.data;
return map;
}
}
Using the Datalist array you can do the following:
var dataList = [
{"Data": "compressedata"},
{"Data": "compressedData"}
];
var compressedData = dataList
.map((item) => item["Data"])
.reduce((value, element) => value + element);
print(compressedData); // compressedatacompressedData

Flutter parsing JSON with array

I have troubles with parsing a JSON file with array.
It looks like something like this:
{
"status": "200",
"addresses": [
{
"address": "Address 1"
},
{
"address": "Address 2"
}
]
}
And I tried to parse it with:
var response = jsonDecode(res.body);
print(response['addresses']['address'][0]);
print(response['addresses']['address'][1]);
But it is not working. Is there any common pattern how this should be?
That's because you're not accessing it the right way. You have a Map<String,dynamic> that has a List<Map<String,String>> for the key addresses.
If you want to access the first two elements of that list, you can do it by doing:
var response = jsonDecode(res.body);
print(response['addresses'][0]['address']);
print(response['addresses'][1]['address']);
The easiest way I have found for dealing with this is to have this website write the JSON parser for me. Simply copy / paste you JSON into provide field and choose Dart as the language:
https://app.Quicktype.io
Your best mapping the data into a class there is a useful website (created by Javier Lecuona) that generates the class for you. https://javiercbk.github.io/json_to_dart/
Here is an example:
var parsedJson = jsonDecode(json);
var addressList = ClientAddresses.fromJson(parsedJson);
print(addressList.addresses[0].address);
print(addressList.addresses[1].address);
class ClientAddresses {
String status;
List<Addresses> addresses;
ClientAddresses({this.status, this.addresses});
ClientAddresses.fromJson(Map<String, dynamic> json) {
status = json['status'];
if (json['addresses'] != null) {
addresses = new List<Addresses>();
json['addresses'].forEach((v) {
addresses.add(new Addresses.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
if (this.addresses != null) {
data['addresses'] = this.addresses.map((v) => v.toJson()).toList();
}
return data;
}
}
class Addresses {
String address;
Addresses({this.address});
Addresses.fromJson(Map<String, dynamic> json) {
address = json['address'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['address'] = this.address;
return data;
}
}