How to extract data from a multipart/form-data response? - flutter

I am uploading images to a storageAPI using POST method with content-type of multipart/form-data. The api returns an object response that looks as below:
{
"id": "6d50c066-cf65-4748-8b9a-183c3526f49b",
"name": "hotel_6.jpg",
"fileKey": "lv/im/5d9feb8e-2ea8-439d-a550-1e937081e085-hotel_6.jpg",
"fileExtension": ".jpg",
"mimeType": "image/jpeg",
"catalogueUrl": {
"mainUrl": "https://xy.abc.com/lv/im/5d9feb8e-2ea8-439d-a550-1e937081e085-hotel_6.jpg",
"thumbnailUrls": []
},
"createdAt": "2021-11-25T06:40:40.0869466+00:00"
}
How can I extract the variable "mainUrl" from the response so that I can assign its value to the _pictureController? Here is what I have done:
uploadFile() async {
var accessToken = await sharedPref.read(key);
var postUrl = '$baseUrl/catalogue?thumbnail=${param.thumbnailTrueFalse}';
Map < String, String > headers = {
"Authorization": "Bearer $accessToken",
};
// multipart request object
var request = http.MultipartRequest("POST", Uri.parse(postUrl));
request.headers.addAll(headers);
// add selected file with request
request.files.add(http.MultipartFile("file", imageStream, imageSize,
filename: imageName));
// Send request
var response = await request.send();
// Read response
var result = await response.stream.bytesToString();
print('readResponse: $result');
if (response.statusCode == 200) {
var data = StorageResponse.fromJson(jsonDecode(result));
print('data: $data');
setState(() {
_pictureController.text = data.catalogueUrl!.mainUrl!;
});
return data;
} else {
throw Exception('Failed to upload photo.');
}
}
The "StorageResponse" Class is as follows:
#JsonSerializable()
class StorageResponse {
var id;
var name;
var fileKey;
var fileExtension;
var mimeType;
Catalogue ? catalogueUrl;
var createdAt;
StorageResponse({
this.id,
this.name,
this.fileKey,
this.fileExtension,
this.mimeType,
this.catalogueUrl,
this.createdAt,
});
factory StorageResponse.fromJson(Map < String, dynamic > json) =>
_$StorageResponseFromJson(json);
Map < String, dynamic > toJson() => _$StorageResponseToJson(this);
#override
toString() {
String output =
'{id:${this.id},name:${this.name},fileKey: ${this.fileKey},fileExtension:${this.fileExtension},mimeType: ${this.mimeType}mimeType},catalogueUrl: ${this.catalogueUrl},,createdAt: ${this.createdAt}}';
return output;
}
}

You can use the following structure to convert a Json file to a class, and vice versa.
The following structure works properly.
import 'dart:convert';
class StorageResponse {
final String id;
final String name;
final String fileKey;
final String fileExtension;
final String mimeType;
Catalogue catalogueUrl;
final DateTime createdAt;
StorageResponse(
this.id,
this.name,
this.fileKey,
this.fileExtension,
this.mimeType,
this.catalogueUrl,
this.createdAt,
);
factory StorageResponse.fromMap(Map<String, dynamic> json) {
return StorageResponse(
json['id'],
json['name'],
json['fileKey'],
json['fileExtension'],
json['mimeType'],
Catalogue.fromMap(json['Catalogue']),
DateTime.parse(json['createdAt']));
}
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'fileKey': fileKey,
'fileExtension': fileExtension,
'mimeType': mimeType,
'Catalogue': catalogueUrl.toJson(),
'createdAt': createdAt
};
#override
toString() {
String output =
'{id:${this.id},name:${this.name},fileKey: ${this.fileKey},fileExtension:${this.fileExtension},mimeType: ${this.mimeType}mimeType},catalogueUrl: ${this.catalogueUrl},,createdAt: ${this.createdAt}}';
return output;
}
}
class Catalogue {
final String mainUrl;
final List<String> thumbnailUrls;
Catalogue(this.mainUrl, this.thumbnailUrls);
factory Catalogue.fromMap(Map<String, dynamic> json) {
return Catalogue(json['mainUrl'], jsonDecode(json['thumbnailUrls']));
}
Map<String, dynamic> toJson() =>
{'mainUrl': mainUrl, 'thumbnailUrls': jsonEncode(thumbnailUrls)};
}
for use
if (response.statusCode == 200) {
var data = StorageResponse.fromMap(jsonDecode(result));
print('data: $data');
setState(() {
_pictureController.text = data.catalogueUrl!.mainUrl!;
});
return data;
} else {
throw Exception('Failed to upload photo.');
}

Related

flutter search from API Json

Im trying to make a searchbar that fetch data from mysql , but i have a problem that when i call data fetch function it returns
Instance of '_Future<List>'
this is my code
Future<List<Students>> getStudents(String id) async {
var url = 'http://localhost/getStudents.php';
final response = await http.post(Uri.parse(url), body: {
'id':id,
});
var res = jsonDecode(response.body)['fname'] as List;
if (response.statusCode == 200) {
return res.map((std) => Students.fromJson(std)).toList();
}else {
throw Exception('Failed to load shows');
}
}
my class :
class Students{
final int id;
final String fname;
final String sname;
final String tname;
const Students( {
required this.id,
required this.sname,
required this.tname,
required this.fname,
});
factory Students.fromJson(Map<String, dynamic> json) => Students(
id: json['Id'],
sname: json['secname'],
tname:json['thirdname'] ,
fname: json['firstname'],
);
}
getStudents is a future function and you need to await for it:
List<Students> result = await getStudents('');

How can I map items from json with http get method flutter?

I`m trying to use an http get method in flutter, but my json is returned like this:
{"items":[{"id":1,"nome":"Ricardo","telefone":"(14) 99797-5621"}],"hasMore":false,"limit":25,"offset":0,"count":1,"links":[{"rel":"self","href":"http://172.16.30.120:8080/ords/apiteste/integrafoods/users"},{"rel":"describedby","href":"http://172.16.30.120:8080/ords/apiteste/metadata-catalog/integrafoods/item"},{"rel":"first","href":"http://172.16.30.120:8080/ords/apiteste/integrafoods/users"}]}
And i`m trying to retrieve info this way:
Future<void> _loadUsers() async {
final response = await http.get(
Uri.parse(_url),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
);
if (response.body == 'null') return;
Map<String, dynamic> data = jsonDecode(response.body);
data.forEach(
(items, userData) {
teste.add(
AppUser(
id: items,
login: userData['login'],
phoneNumber: userData['telefone'],
),
);
},
);
print(_teste.length);
}
But it's not working, it throws error: "[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'".
But if i use code this way, it returns all parameters from the json:
Future<void> _loadUsers() async {
final response = await http.get(
Uri.parse(_url),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
);
if (response.body == 'null') return;
Map<String, dynamic> data = jsonDecode(response.body);
data.forEach(
(items, userData) {
teste.add(
AppUser(
login: userData['items'].toString(),
),
);
},
);
print(_teste.length);
}
How can i map this "items" json so i get each parameter separetadely?
class AppUser {
// final String CPF;
final String id;
final String? login;
final String? name;
final String? email;
final String? situation;
final String? phoneNumber;
final String? password;
final String? inclusionDt;
final String? inclusionUs;
final String? altDt;
final String? altUs;
final String company;
const AppUser({
// required this.CPF,
required this.id,
this.login,
this.name,
this.email,
this.situation,
this.phoneNumber,
this.password,
this.inclusionDt,
this.inclusionUs,
this.altDt,
this.altUs,
this.company = 'GTFoods',
});
}
You can use this model class
import 'dart:convert';
class MyItem {
final int id;
final String? nome;
final String? telefone;
MyItem({
required this.id,
required this.nome,
required this.telefone,
});
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
result.addAll({'id': id});
if (nome != null) {
result.addAll({'nome': nome});
}
if (telefone != null) {
result.addAll({'telefone': telefone});
}
return result;
}
factory MyItem.fromMap(Map<String, dynamic> map) {
return MyItem(
id: int.tryParse(map['id'].toString()) ?? 0,
nome: map['nome'],
telefone: map['telefone'],
);
}
String toJson() => json.encode(toMap());
factory MyItem.fromJson(String source) => MyItem.fromMap(json.decode(source));
}
Try using
final data = jsonDecode(response.body)['items'] as List?;
if (data != null) {
final items = data.map((e) => MyItem.fromJson(e)).toList();
print(data);
}

I am trying to get data from API but having error

This is my model class and I am trying to get all the data but getting error and don't know why.
HomePageModel homePageModelFromJson(String str) => HomePageModel.fromJson(json.decode(str));
String homePageModelToJson(HomePageModel data) => json.encode(data.toJson());
class HomePageModel with ChangeNotifier {
HomePageModel({
this.data,
});
List<Datum>? data;
factory HomePageModel.fromJson(Map<String, dynamic> json) => HomePageModel(
data: List<Datum>.from(json["data"]!.map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data!.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.schoolid,
this.name,
this.logo,
this.address,
this.contact,
this.principalname,
this.principalcontact,
this.slogan,
this.webAddress,
this.description,
this.email,
this.pan,
this.establishedYear,
});
String? schoolid;
String? name;
String? logo;
String? address;
String? contact;
String? principalname;
String? principalcontact;
String? slogan;
String? webAddress;
String? description;
String? email;
String? pan;
int? establishedYear;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
schoolid: json["schoolid"],
name: json["name"],
logo: json["logo"],
address: json["address"],
contact: json["contact"],
principalname: json["principalname"],
principalcontact: json["principalcontact"],
slogan: json["slogan"],
webAddress: json["web_address"] == null ? null : json["web_address"],
description: json["description"] == null ? null : json["description"],
email: json["email"],
pan: json["pan"],
establishedYear: json["established_year"],
);
Map<String, dynamic> toJson() => {
"schoolid": schoolid,
"name": name,
"logo": logo,
"address": address,
"contact": contact,
"principalname": principalname,
"principalcontact": principalcontact,
"slogan": slogan,
"web_address": webAddress == null ? null : webAddress,
"description": description == null ? null : description,
"email": email,
"pan": pan,
"established_year": establishedYear,
};
}
This is how I am trying to fetch data:
class HomePageModels with ChangeNotifier{
List<HomePageModel> _hItem = [];
List<HomePageModel> get hItem{
return [..._hItem];
}
Future<void> getHomeData(BuildContext context) async{
const url = "https://shikshyasoftware.com.np/CoreApplicationandAPIService-4617993073/api/school";
try{
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
List<HomePageModel> loadedHomeData = [];
if(extractedData == null){
return;
}
if(response.statusCode == 200){
print(extractedData);
}
extractedData.forEach((element){
loadedHomeData.add(HomePageModel.fromJson(element));
});
_hItem = loadedHomeData;
// EasyLoading.showSuccess("data fetched sucessfull");
notifyListeners();
}catch(e){
rethrow;
}
}
}
But I am getting error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '(dynamic) => Null' is not a subtype of type '(String, dynamic) => void' of 'f'
The problem is the way you are trying to parse the data, you don't need to loop over every element to parse it, in your model just make it return a list type like this,
class HomePageModel with ChangeNotifier {
List<Datum>? data;
HomePageModel({this.data});
HomePageModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = <Datum>[];
json['data'].forEach((v) {
data!.add(new Datum.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Datum {
Datum({
this.schoolid,
this.name,
this.logo,
this.address,
this.contact,
this.principalname,
this.principalcontact,
this.slogan,
this.webAddress,
this.description,
this.email,
this.pan,
this.establishedYear,
});
String? schoolid;
String? name;
String? logo;
String? address;
String? contact;
String? principalname;
String? principalcontact;
String? slogan;
String? webAddress;
String? description;
String? email;
String? pan;
int? establishedYear;
Datum.fromJson(Map<String, dynamic> json) {
schoolid = json["schoolid"];
name = json["name"];
logo = json["logo"];
address = json["address"];
contact = json["contact"];
principalname = json["principalname"];
principalcontact = json["principalcontact"];
slogan = json["slogan"];
webAddress = json["web_address"];
description = json["description"];
email = json["email"];
pan = json["pan"];
establishedYear = json["established_year"];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['schoolid'] = this.schoolid;
data['name'] = this.name;
data['logo'] = this.logo;
data['address'] = this.address;
data['contact'] = this.contact;
data['principalname'] = this.principalname;
data['principalcontact'] = this.principalcontact;
data['slogan'] = this.slogan;
data['web_address'] = this.webAddress;
data['description'] = this.description;
data['email'] = this.email;
data['pan'] = this.pan;
data['established_year'] = this.establishedYear;
return data;
}
}
and in your view model you can just parse the extracted data from response.body like this,
class HomePageModels with ChangeNotifier {
HomePageModel? _hItem;
HomePageModel get hItem {
return _hItem!;
}
Future<void> getHomeData(BuildContext context) async {
const url =
"https://shikshyasoftware.com.np/CoreApplicationandAPIService-
4617993073/api/school";
try {
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
if (extractedData == null) {
return;
}
if (response.statusCode == 200) {
print(extractedData);
}
HomePageModel loadedHomeData =
HomePageModel.fromJson(extractedData);
_hItem = loadedHomeData;
// EasyLoading.showSuccess("data fetched sucessfull");
notifyListeners();
} catch (e) {
rethrow;
}
}
}
getHomeData(BuildContext context) async {
const url =
"https://shikshyasoftware.com.np/CoreApplicationandAPIService-4617993073/api/school";
try {
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final extractedData = json.decode(response.body);
List loadedHomeData = extractedData;
_hItem = loadedHomeData.map((e) => HomePageModel.fromJson(e)).toList();
}
notifyListeners();
return _hItem;
} catch (e) {
rethrow;
}
}

Model a server response with Class

I have a flutter application, which uses some server APIs.
When there is a successful response from the server, it would return json back:
{"success": true, "message": "success", "data": {"id": "21EE"} }
However, when there is failure, it would return:
{"success": false, "message": "failure"}
For more strict-typed use of flutter, I try to model the response.
Here is my try:
class ServerResponse {
final bool success;
final String message;
ServerResponse({
required this.success,
required this.message,
});
}
class _AuthAutenticationData {
final String id;
_AuthAutenticationData({
required this.id,
});
}
class AutoAuthenticateResponse extends ServerResponse {
final _AuthAutenticationData? data;
AutoAuthenticateResponse({
required success,
required message,
this.data,
}) : super(success: success, message: message);
}
Now, I have a function which calls a specific API:
Future<void> autoAuth() async {
final url = Uri.parse('${this._baseURL.toString()}/auto-auth');
try {
final response = await http.post(url, headers: {
'Authorization': 'SXXX',
});
print(response.body);
final AutoAuthenticateResponse responseBody = json.decode(response.body);
if (responseBody.success) {
return setUser(new User(id: responseBody.data!.id));
}
setUser(null);
} catch (error) {
print(error);
setUser(null);
}
}
Some code is irrelevant, but bottom line is that I receive the following error in the line: final AutoAuthenticateResponse responseBody = json.decode(response.body);:
I/flutter (14139): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'AutoAuthenticateResponse'
I guess my solution is bad. Any advice how to fix it?
Well, you can use nullsafety feature for this. Since it's only if when the failure the data is not being returned.
{"success": true, "message": "success", "data": {"id": "21EE"} }
you can use this :
https://meruya-techhnology.github.io/json-to-dart/
Then the result will be a 2 class
class YourClass {
final bool success;
final String message;
final Data? data;
YourClass({this.success, this.message, this.data});
factory YourClass.fromJson(Map<String, dynamic> json) => YourClass(
success : json['success'],
message : json['message'],
data : json['data'] != null ? new Data.fromJson(json['data']) : null;
);
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['success'] = this.success;
data['message'] = this.message;
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
And
class Data {
String id;
Data({this.id});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
return data;
}
}
Then you can use it like this :
Future<void> autoAuth() async {
final url = Uri.parse('${this._baseURL.toString()}/auto-auth');
try {
final response = await http.post(url, headers: {
'Authorization': 'SXXX',
});
debugPrint(response.body);
final responseBody = YourClass.fromJson(response.body)
if (responseBody.success) {
return setUser(new User(id: responseBody.data!.id));
}
setUser(null);
} catch (error) {
print(error);
setUser(null);
}
}
another advice is use debugPrint instead of print, here you can read more : https://medium.com/flutter-community/debugprint-and-the-power-of-hiding-and-customizing-your-logs-in-dart-86881df05929
Use this link to generate models for your response

Error FormatException: Unexpected character (at character 1) <br/> Flutter

I want to showing this value to listview on flutter
[{"No":0,"interest":"0.00","balance":"13,000,000.00","principal":"0.00","Installment":"0.00","Status":true},{"No":1,"interest":"130,000.00","balance":"0.00","principal":"13,000,000.00","Installment":"13,130,000.00","Status":true}]
but i get the result like
I/flutter (12074): Error FormatException: Unexpected character (at character 1)
I/flutter (12074): <br />
I/flutter (12074): ^
I/flutter (12074):
here is my List LoanModel
static Future<List<LoanModel>> getsimulation({String periodtime, String interestpermonth, String loanamountrequest, String idUser, String url}) async {
var url = "http://192.168.0.23/edufund-api/Api/loansimulation.php?periodtime=" + periodtime + "&interestpermonth=" + interestpermonth + "&loanamountrequest=" +loanamountrequest;
final response = await http.get(url,headers:{"Content-Type":
"application/json"});
var res = LoanModel.fromJson(jsonDecode(response.body)[0]);
print(response.body);
}
here is the function to load JSON when already input value periodtime, interestpermonth and loanamountrequest
_load() async {
List<LoanModel> loanmodel =
(await RestApi.getsimulation());
setState(() => _loanmodel = loanmodel);
}
Here is my Model
List<LoanModel> allLoan(String str) {
final jsonData = json.decode(str);
return new List<LoanModel>.from(jsonData.map((x) => LoanModel.fromJson(x)));
}
class LoanModel {
bool Status;
String message;
String No;
String interest;
String balance;
String principal;
String Installment;
List<Data> data;
LoanModel({
this.Status,
this.message,
this.No,
this.interest,
this.balance,
this.principal,
this.Installment,
this.data,
});
factory LoanModel.fromJson(Map<String, dynamic> parsedJson) {
var list = parsedJson['data'] as List;
print(list.runtimeType);
List<Data> dataList = list.map((i) => Data.fromJson(i)).toList();
return LoanModel(
Status: parsedJson['Status'],
message: parsedJson['message'],
No : parsedJson['No'],
interest: parsedJson['interest'],
balance: parsedJson['balance'],
principal: parsedJson['principal'],
Installment: parsedJson['Installment'],
data: dataList,
);
}
}
class Data {
final int No;
final String interest;
final String balance;
final String principal;
final String Installment;
Data({
this.No,
this.interest,
this.balance,
this.principal,
this.Installment
});
factory Data.fromJson(Map<String, dynamic> parsedJson) {
return Data(
No: parsedJson['No'],
interest: parsedJson['interest'],
balance: parsedJson['balance'],
principal: parsedJson['principal'],
Installment: parsedJson['Installment']
);
}
and the result is keep loading like this
The output should be like this
How can i make output like picture number 2 and how to resolved this Unexpected character in flutter?
thank you
I am able to parse it with the JSON locally. Update the dataModel:
import 'dart:convert';
List<LoanModel> loanModelFromJson(String str) => List<LoanModel>.from(json.decode(str).map((x) => LoanModel.fromJson(x)));
String loanModelToJson(List<LoanModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class LoanModel {
LoanModel({
this.no,
this.interest,
this.balance,
this.principal,
this.installment,
this.status,
});
int no;
String interest;
String balance;
String principal;
String installment;
bool status;
factory LoanModel.fromJson(Map<String, dynamic> json) => LoanModel(
no: json["No"],
interest: json["interest"],
balance: json["balance"],
principal: json["principal"],
installment: json["Installment"],
status: json["Status"],
);
Map<String, dynamic> toJson() => {
"No": no,
"interest": interest,
"balance": balance,
"principal": principal,
"Installment": installment,
"Status": status,
};
}
Any try to parse it like this:
arr = loanModelFromJson(response.body);
RestAPI call
class APIManager {
final String baseURL = [BaseURL];
getData(apiUrl) async {
var fullUrl = baseURL + apiUrl;
return await http.get(Uri.parse(fullUrl), headers: _setHeader());
}
}
Future<void> getData() async {
var response = await APIManager().getData([Endpoint]);
arr = loanModelFromJson(response.body);
}