How to handle difference responses API? - flutter

How to handle the difference between the results of a successful and failed fire response?
RESPONSE SUCCESS:
{
"header":{
"status":true,
"respcode":"00",
"message":"Successfully."
},
"data":{
"userid":"3485345",
"password":"3423424",
"bit18":"0000",
}
}
RESPONSE FAILED:
{
"header":{
"status":false,
"respcode":"01",
"message":"Userid Tidak Terdaftar"
},
"data":""
}

assuming you'll always have headers in your responses, you can do something like this:
Map<String, dynamic> res1 = {
"header": {"status": true, "respcode": "00", "message": "Successfully."},
"data": {
"userid": "3485345",
"password": "3423424",
"bit18": "0000",
}
};
Map<String, dynamic> res2 = {
"header": {
"status": false,
"respcode": "01",
"message": "Userid Tidak Terdaftar"
},
"data": ""
};
// bla = res2 for failed case
final bla = res1;
if (bla['header']['status']) {
print(res1['data']['userid']);
// do your success code here
} else {
// do your fail code here
print('fail');
}

I don't know why in the failed case, data is string (and not object). In theory, the failed case should have an empty object instead of a string. Any way, assuming you don't have control over the server's response, you might want to do something like below :
(The first two lines I wrote just to make sure the parsing works.)
Map<String, dynamic> mData = {
"header":{
"status":true,
"respcode":"00",
"message":"Successfully."
},
"data":{
"userid":"3485345",
"password":"3423424",
"bit18":"0000",
}
};
String jData = json.encode(mData);
Map<String, dynamic> decodedBody = json.decode(jData);
print(decodedBody["header"]["respcode"]); // prints 00
if (decodedBody['header']['status'])
{
User user = User.fromJson(decodedBody['data']);
print(user.userId); // This prints 3485345
}
else {
// login failed
}
And the User model is defined as below :
class User {
final String userId;
final String password;
final String bit18;
User({#required this.userId, #required this.password, this.bit18});
User.fromJson(Map json)
: this.userId = json['userid'],
this.password = json['password'],
this.bit18 = json['bit18'];
}

Related

Flutter model doesnt work with different responses

I have a Fluter Model User
class User {
String id;
String name;
String email;
String image;
User({
this.id = "",
this.name = "",
this.email = "",
this.image = "",
});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'],
email: json['email'],
image: json['image'],
);
}
Map toMap() {
var map = Map<String, dynamic>();
map['id'] = id;
map['name'] = name;
map['email'] = email;
map['image'] = image;
return map;
}
}
And I have a flutter LoginResult that calls user model when I do login
import 'User.dart';
class LoginResult {
String message;
String? token;
User? user;
LoginResult({
this.message = "",
this.token,
this.user,
});
factory LoginResult.fromJson(Map<String, dynamic> json) {
if (json['user'] != null) {
return LoginResult(
message: json['message'],
user: User.fromJson(json['user']),
token: json['token'],
);
} else {
return LoginResult(
message: json['message'],
token: json['token'],
);
}
}
Map toMap() {
var map = Map<String, dynamic>();
map['message'] = message;
map['user'] = user;
map['token'] = token;
return map;
}
}
When I do login, the parsing response body in LoginResults works fine with this result json
{
"message": "logged in success",
"user": {
"rol": 100,
"image": "83f124c1-5a46-469c-8de7-11a90c506a44.jpg",
"_id": "6105c3c8bf76720bfa2e31e9",
"name": "Guillermo Canales Justo",
"email": "test#email.com",
"password": "$2b$10$Z5.RMoRHeyKt7cdFrtubbOzEGjGvHhU19UQEV.mA/ZSunIXqKhYz.",
"__v": 48,
"created": "2021-09-18T06:52:40.995Z",
"id": "6105c3c8bf76720bfa2e31e9"
},
"token": "eyJhbGciOiJIUzI..."
}
But when I update profile user and returns this json, User.fromJson(json_decode(response.body)) returns properties null.
email:null
id:null
image:null
name:null
hashCode:258164629
runtimeType:Type (User)
with this json response
{
"user": {
"rol": 100,
"image": "595ccd2c-1c37-42a7-904f-fdc73b5f89b0.jpg",
"_id": "6105c3c8bf76720bfa2e31e9",
"name": "Guillermo Canales",
"email": "test#email.com",
"password": "$2b$10$Z5.RMoRHey...",
"__v": 48,
"created": "2021-09-18T06:52:40.995Z",
"id": "6105c3c8bf76720bfa2e31e9"
}
}
I cant understand what's wrong with the second parsing.
you will have to get the Users from the json.
change this line
User.fromJson(json_decode(response.body))
to
User.fromJson(json_decode(response.body)['user'])

Flutter Bloc: Return custom constructor object as the state

I have created a model for users details which will be returned after a post request.
Model:
class Did {
String message;
bool success;
String id;
String docHash;
String pubKey;
String privKey;
Object credential;
Did.fromJson(Map<String, dynamic> json)
: message = json["message"],
success = json["success"],
id = json["id"],
docHash = json["docHash"],
pubKey = json["pubKey"],
privKey = json["privKey"],
credential = json["credential"];
}
I'm calling the post request inside of the repository which gets called from the Bloc. The response of the post request gets parsed with my Model and than returned to the bloc. I now want to set the state to SubmissionSuccess with the data of the parsed json. This is the relevant extract of my Bloc which calls the repository:
class CreateDidBloc extends Bloc<CreateDidEvent, CreateDidState> {
final CreateDidRepository? repo;
CreateDidBloc({this.repo}) : super(CreateDidState());
#override
Stream<CreateDidState> mapEventToState(CreateDidEvent event) async* {
if (event is CreateDidFirstNameChanged) {
...
} else if (event is CreateDidSubmitted) {
yield state.copyWith(formStatus: FormSubmitting());
try {
final res = await repo?.createDid(
state.firstname,
state.lastName,
state.email,
state.phoneNumber,
state.dateOfBirth,
state.sex,
state.address,
state.city,
state.state,
state.postalCode,
state.country);
yield state.copyWith(formStatus: SubmissionSuccess(did: res));
} catch (e) {
yield state.copyWith(formStatus: SubmissionFailed(exception: e)); // e is not an exception but an Object ...why
}
}
}
}
And this is the repository which creates the post request and returns the json response as a <Did> Object. I now want to set this object as the state of the form submission when the submission is successfull.
class CreateDidRepository {
Dio dio = Dio();
Future<Did> createDid(
String firstName,
String lastName,
String email,
String phoneNumber,
DateTime? dateOfBirth,
String sex,
String address,
String city,
String state,
String postalCode,
String country) async {
var res = await dio.post("http://did-backend.herokuapp.com/create",
data: {
"firstName": firstName.trim(),
"lastName": lastName.trim(),
"email": email.trim(),
"phoneNumber": phoneNumber.trim(),
"dateOfBirth": dateOfBirth?.toIso8601String(),
"sex": sex.trim(),
"address": address.trim(),
"city": city.trim(),
"state": state.trim(),
"postalCode": postalCode.trim(),
"country": country.trim()
},
options: Options(headers: {
Headers.contentTypeHeader: "application/json",
}));
if (res.statusCode == 200) {
final json = jsonDecode(res.toString());
print(json);
return Did.fromJson(json);
}
throw "Identity request failed";
}
}
This is my form submission state (blow) but I can't seem to figure out how to set the right type of the <Did> object to accept the return value of the repository. My question is, what type do I have to define the did object to?
abstract class FormSubmissionStatus {
const FormSubmissionStatus();
}
class InitialFormStatus extends FormSubmissionStatus {
const InitialFormStatus();
}
class FormSubmitting extends FormSubmissionStatus {}
class SubmissionSuccess extends FormSubmissionStatus {
final <Did> did; //error
SubmissionSuccess({required this.did});
}
class SubmissionFailed extends FormSubmissionStatus {
final Exception exception;
SubmissionFailed({required this.exception});
}
Small extra error: The catch block inside my bloc returns an Object instead of an exception, so I can't assign that to the exception class of the SubmissionFailed state. Why does it return and Object?
Edit:
Example response of post request.
{
"id": "7hvu33b3QqWzSWVC1hmLMhLiT5PbrT8JH8JFCjPir2Ke",
"docHash": "FIJ9HZNASYIBIH9QSBSXZBSXQGRARUPGZNMAVOYPUJIXTATLSCNM9WUSLYYZWKGUVBUDLFV9UQYBA9999",
"pubKey": "GpoGnXs5S2vyMGeSxWoy7gEmyySXyrbTkX7oCcEfyuAR",
"privKey": "4MKNYQKfeqSXSV7faLSYjAY3SjysnVgHzax9LdfZYVmZ",
"credential": {
"#context": "https://www.w3.org/2018/credentials/v1",
"id": "http://example.edu/credentials/3732",
"type": [
"VerifiableCredential",
"personalInformationCredential"
],
"credentialSubject": {
"id": "did:iota:7hvu33b3QqWzSWVC1hmLMhLiT5PbrT8JH8JFCjPir2Ke",
"address": {
"street": "address",
"city": "city",
"state": "state",
"postalCode": "postalCode",
"country": "country"
},
"dateOfBirth": "dateOfBirth",
"email": "email",
"name": {
"first": "firstName",
"last": "lastName"
},
"phoneNumber": "phoneNumber",
"sex": "sex"
},
"issuer": "did:iota:A5STNhet1zgGbbnZCqniokcAdXbZZ2xcE6QWruQmctEs",
"issuanceDate": "2021-04-23T22:02:02Z",
"proof": {
"type": "MerkleKeySignature2021",
"verificationMethod": "#key-collection",
"signatureValue": "3RypuceLDTQt1Anb9WdBj7ayPS91EdiYJ6ELPMChgocm.1117tuDcgbUJddXaLoFqvAh8WWeypGnCTuPCDggJ2cMk6AVyJAjHaaCgSmgaKsGa299TxVBqfypgqbjQx1gExf2kkD9XU8ViYhZRVm9dx5qELnVxcM2H5R5YmL6rLn3RR6SbiNSc7XG.3icG5TLDkVBd8UR82LvWYgarBL6SZbFzAcDebvjkVK9wqgn1kp5LhHtp5NpzbEXeLHJzRo5GBoWihsKndffjRSDk"
}
},
"message": "You have successfully created your digital identity, firstName",
"success": true
}
please use this website to convert you'r json to dart class.
please instead of :
if (res.statusCode == 200) {
final json = jsonDecode(res.toString());
print(json);
return Did.fromJson(json);
}
use this :
if (res != null && res.statusCode == 200) {
return Did.fromJson(response.data);
}
and believe me, use different state class for different situation, here for example you use same state for progress, error and loaded.
I hope i was able to help.

Push array into list flutter

So i'm trying to create a list with objects of type 'MessageListItem'. I'm trying to push data returned from my API into the list. The variable I want it pushed into is 'messages'. I am getting an error in the 'getMessages()' function.
The error I am getting is: A value of type 'MessageListItem' can't be assigned to a variable of type 'List'.
The API call & code is:
List<MessageListItem> messages;
getMessages() async {
List<MessageListItem> res = MessageListItem.fromJson(await getMessageList());
// I'm getting the error on the line above.
print(res);
}
Future<dynamic> getMessageList() async {
final response = await http.get(baseUrl + 'message/jxchumber');
print(response.statusCode);
if (response.statusCode == 200) {
var res = json.decode(response.body);
return res;
} else {
throw Exception('Failed to get data');
}
}
MessageListItem Class
class MessageListItem {
int id;
int senderId;
int recipientId;
String senderUsername;
String recipientUsername;
int itemId;
String messageContentString;
bool read;
dynamic dateTimeSent;
MessageListItem(
{this.id,
this.senderId,
this.recipientId,
this.senderUsername,
this.recipientUsername,
this.itemId,
this.messageContentString,
this.read,
this.dateTimeSent});
factory MessageListItem.fromJson(Map<String, dynamic> json) {
return MessageListItem(
id: json['id'],
senderId: json['senderId'],
recipientId: json['recipientId'],
senderUsername: json['senderUsername'],
recipientUsername: json['recipientUsername'],
itemId: json['itemId'],
messageContentString: json['messageContentString'],
read: json['read'],
dateTimeSent: json['dateTimeSent'],
);
}
}
The data being returned from the API is:
[
{
"id": 4,
"senderId": 1,
"recipientId": 3,
"senderUsername": "jxchumber",
"recipientUsername": "pavster31",
"itemId": 0,
"messageContentString": "hello1",
"read": false,
"dateTimeSent": "2020-12-14T22:23:55.1473414"
},
{
"id": 3,
"senderId": 1,
"recipientId": 9,
"senderUsername": "jxchumber",
"recipientUsername": "larsen",
"itemId": 0,
"messageContentString": "hello1",
"read": false,
"dateTimeSent": "2020-12-14T16:04:50.8232055"
}
]
I'm trying to push it into the variable 'messages'
Try this
getMessages() async {
var list = await getMessageList();
List<MessageListItem> res = list.map((i)=>MessageListItem.fromJson(i)).toList();
}

Flutter: Parsing JSON array

I'm trying out http requests from flutter to my backend.
My JSON is like this:
"_hits": {
"Do8HpM3w0mh99SF": {
"docid": "Do8HpM3w0mh99SF"
},
"HNLvkccTCIlmrcQ": {
"docid": "HNLvkccTCIlmrcQ"
},
"QNSInDU2BJMF5SD": {
"docid": "QNSInDU2BJMF5SD"
},
"UVDfRueZXIVCssk": {
"docid": "UVDfRueZXIVCssk"
},
"Y9bNKklTr2Sg6Ai": {
"docid": "Y9bNKklTr2Sg6Ai"
},
"kJgwwMbgF6PBwmMJSiKC": {
"docid": "kJgwwMbgF6PBwmMJSiKC"
},
"py5MbGK11SsbXQ1": {
"docid": "py5MbGK11SsbXQ1"
}
}
My code to request:
Future<SearchResults> fetchJson() async {
final response =
await http.get('MyWebsite.com');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
// print(response.body);
return SearchResults.fromJson(json.decode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load request');
}
}
The Search Results Class:
class SearchResults {
final String hits;
SearchResults({this.hits});
factory SearchResults.fromJson(Map<String, dynamic> json) {
return SearchResults(
hits: json['_hits'],
);
}
}
What I'm trying to achieve:
Print the value of docid under the array of _hits
Coming From iOS Swift, this is very new to me, any input is greatly appreciated.
Your SearchResuts object is wrong as _hits is not a String but a Map<String, dynamic> to do it simple :
class SearchResults {
Map<String, dynamic> hHits;
SearchResults({this.hHits});
SearchResults.fromJson(Map<String, dynamic> json) {
hHits = json['_hits'];
}
}
From here, you can iterate on your docids by getting a list of _hits elements like this :
print(searchResults.hHits.values.toList());
will print
[{docid: Do8HpM3w0mh99SF}, {docid: HNLvkccTCIlmrcQ}, {docid: QNSInDU2BJMF5SD}, {docid: UVDfRueZXIVCssk}, {docid: Y9bNKklTr2Sg6Ai}, {docid: kJgwwMbgF6PBwmMJSiKC}, {docid: py5MbGK11SsbXQ1}]

Difficulty in parsing JSON

I want to develop a flutter app and I am finding it difficult to parse this JSON I have seen posts regarding this but I am finding it difficult to parse this. Help a beginner out! Here is the JSON link " https://api.covid19india.org/state_district_wise.json "
I am simply using:
Future getJsonDistrictData() async {
var response = await http.get(Uri.encodeFull(url1));
var converttojson1 = json.decode(response.body);
setState(() {
myData= converttojson1;
});
}
Text("${myData['Kerala']['districtData']['Thrissur']['confirmed']}")
But this would mean I have to write the same line for every district confirmed cases.
How should I proceed?
I have made the following example of an implementation you can use the parse the data from the URL in your question.
It can be simplified if you don't need the lastUpdatedTime and delta_confirmed since it looks like this is always the empty String and zero in the API.
import 'dart:convert';
class State {
final Map<String, DistrictData> districts = {};
State.fromJson(dynamic json) {
for (final district in json['districtData'].keys) {
districts[district as String] =
DistrictData.fromJson(json['districtData'][district]);
}
}
#override
String toString() => districts.toString();
}
class DistrictData {
final int confirmed;
final DateTime lastUpdatedTime;
final int delta_confirmed;
DistrictData(this.confirmed, this.lastUpdatedTime, this.delta_confirmed);
factory DistrictData.fromJson(dynamic json) => DistrictData(
json['confirmed'] as int,
(json['lastupdatedtime'].isEmpty as bool)
? null
: (DateTime.parse(json['lastupdatedtime'] as String)),
json['delta']['confirmed'] as int);
#override
String toString() =>
'{ confirmed: $confirmed, lastUpdatedTime: $lastUpdatedTime, delta_confirmed: $delta_confirmed }';
}
void main() {
final states = json.decode(input).map(
(String key, dynamic value) => MapEntry(key, State.fromJson(value)))
as Map<String, State>;
states.forEach((key, value) => print('$key : $value'));
/*
Kerala : {Thrissur: { confirmed: 13, lastUpdatedTime: null, delta_confirmed: 0 }, Alappuzha: { confirmed: 5, lastUpdatedTime: null, delta_confirmed: 0 }}
Delhi : {East Delhi: { confirmed: 1, lastUpdatedTime: null, delta_confirmed: 0 }}
*/
}
const input = '''
{
"Kerala": {
"districtData": {
"Thrissur": {
"confirmed": 13,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
},
"Alappuzha": {
"confirmed": 5,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
}
}
},
"Delhi": {
"districtData": {
"East Delhi": {
"confirmed": 1,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
}
}
}
}
''';
Copy your JSON in this link(https://javiercbk.github.io/json_to_dart/) and get model Class.
Example:
For example your Model Class Name is CovidModel. As you get response from network call, pass data to you model class and get object like this:
CovidModel _covidModel = CovidModel.fromJson(response.data);
now you can use _covidModel to get inner objects and show result in app page.