I have this response body from a http push
"{"identifier":"00000000-0000-0000-0000-00000000000"}"
I'd like to get the 000000... part as string
that's the relevant part of my code
.
.. async {
await http
.post(Uri.encodeFull(mainURL + registrEndPoint + _stuff))
.then((res) {
if (res.statusCode == 202) {
Map _body = jsonDecode(res.body);
// I checked debugging, the respons boy is ok
String _id =_body['identifier'];
return _id;
}...
I believe I'm missing something in the 'mapping'
and I suspect the combo 'quote-curlyBraces-quote'
defeat my jsonDecode;
any suggestion?
thanks in advance
By looking at the dart:convert documentation, you’ll see that jsonDecode() returns a
Map<String, dynamic>, meaning that you do not know the types of the values until runtime.
Map<String, dynamic> body = jsonDecode(jsonString);
print('Howdy, ${body['identifier']}!');
I solved the problem adding this line
String _body = res.body;
as described below,
await http
.post(Uri.encodeFull(mainURL + registrEndPoint + _qr))
.then((res) {
if (res.statusCode == 202) {
String _body = res.body; //<--- HERE!
Map _json = jsonDecode(_body);
String _id = _json['identifier'];
return _id ;
});
Thank you all for the help!
Related
I receive an error that has something to do with JSON receiver inside Flutter/Dart.
Had to share in a docs file since the full json response is pretty long. It had like 15 columns error log
Detail Class
class Detail {
String kodkursus;
String namakursus;
String kursusdescription;
Detail(
{required this.kodkursus,
required this.namakursus,
required this.kursusdescription});
factory Detail.fromJson(Map<String, dynamic> json) {
return Detail(
kodkursus: json['crs_code'] as String,
namakursus: json['crs_title_bm'] as String,
kursusdescription: json['crs_description_bm'] as String,
);
}
}
Code
Future<dynamic> generateDetailList() async {
var url = 'http://10.0.2.2:81/login_testing/kursus_display.php';
var data = {'usr_id': widget.username2};
var response = await http.post(url, body: json.encode(data));
var list = json.decode(json.encode(response.body));
List<Detail> _detail =
list.map<Detail>((json) => Detail.fromJson(json)).toList();
detailDataSource = DetailDataSource(_detail);
return _detail;
}
Return (full error log)
NoSuchMethodError (NoSuchMethodError: Class 'String' has no instance method 'map'...
I fairly new to this Flutter/Dart but I got the feeling it had something to do with the json, it just I cant get my head over it
Please check your API response because this error generates when there are difference in datatype.
this error says your app response it in String and you are accessing this as map so please check your API response or
try to replace this :
var list = json.decode(json.encode(response.body));
with :
var list = json.decode(response.body);
because json.encode method encodes all list data and that values datatype is String so it gives error.
Replace your function generateDetailList as such:
Future<List<Detail>?> generateDetailList() async {
Uri url = Uri.parse('http://10.0.2.2:81/login_testing/kursus_display.php');
Map<String, String> data = {'usr_id': 'widget.username2'};
http.Response response = await http.post(url, body: json.encode(data));
// var list = json.decode(json.encode(response.body));
var responseMap = await jsonDecode(response.body);
if (response.statusCode == 200) {
List<Detail> _details =
responseMap.map<Detail>((x) => Detail.fromJson(x)).toList();
return _details;
} else {
return null;
}
}
And try not to use var everywhere.
Not sure if what I'm trying to do is a foolish en-devour or ? In the app, I use rest API calls and I'm trying to implement API handling with Dio.
I have gone with an approach like so.
each API method has a generic function. ie: the POST method. goes like
Future<dynamic> postRequest({String? endPoint, dynamic decoder, data}) async {
// late String _fullURL = BaseOptions().baseUrl + endPoint!;
late int? _responseCode;
try {
final response = await _dio.post(
endPoint!, // APIEndpoints.postSignUp,
data: data, //jsonEncode(data),
);
//
// final String _responseString = response.data;
_responseCode = response.statusCode;
//
if (_responseCode == 200) {
final String _responseString = response.data;
final res = decoder(_responseString);
log("post success response ------------ ${res.toString()}");
return SuccessHandler().checkSuccess(res);
} else if (_responseCode == 201) {
log("post success no response ------------ ");
return HTTPResponse<dynamic>(
false,
null,
message: 'empty success',
code: _responseCode!,
//'Something went wrong! Please try again in a moment!',
);
} else {
log("post failed response ------------ ");
return null;
// return ErrorHandler().checkError(_responseCode, _responseString);
}
} on DioError catch (e) {
// print(e.message);
// throw Exception(e.message);
log("exception ------------ ${e.message}");
return HTTPResponse<dynamic>(
false,
null,
message: 'error: ${e.message}',
code: e.response!.statusCode!,
//'Something went wrong! Please try again in a moment!',
);
}
}
Where I try to pass the decoder to get the JSON response read out from the API response. Using a generated class like this
ValidateEmailModel validateEmailModelFromJson(String str) =>
ValidateEmailModel.fromJson(json.decode(str));
String validateEmailModelToJson(ValidateEmailModel data) =>
json.encode(data.toJson());
class ValidateEmailModel {
ValidateEmailModel({
this.email,
this.type,
this.code,
this.expire,
this.createdTime,
});
String? email;
String? type;
String? code;
dynamic expire;
dynamic createdTime;
factory ValidateEmailModel.fromJson(Map<String, dynamic> json) =>
ValidateEmailModel(
email: json["email"],
type: json["type"],
code: json["code"],
expire: DateTime.parse(json["expire"].toString()),
createdTime: DateTime.parse(json["createdTime"].toString()),
);
Map<String, dynamic> toJson() => {
"email": email,
"type": type,
"code": code,
"expire": expire!.toIso8601String(),
"createdTime": createdTime!.toIso8601String(),
};
}
In my method calls. i give the function its paramters like so
res = await APIHandler.instance.postRequest(
endPoint: APIEndpoints.postValidateCode,
decoder: validateEmailModelFromJson,
data: {
"code": val,
"email": _email,
},
)
And await the response to be passed to another common method SuccessHandler() so I can get the data object/s
class SuccessHandler {
dynamic successObject;
SuccessHandler({this.successObject});
Future<dynamic> checkSuccess(dynamic response) async {
return SuccessHandler(successObject: response);
}
}
so far when I try to debug the code. I do get the response.data from the Dio response. but gives me
Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
can I achieve what I need to and how can I update the code? Please help me with this or just I think I'm trying to reinvent the wheel here.
validateEmailModelFromJson what this function will do is take a string convert it into json and will parse it you data model but in you postRequest function you are already get a json response from api call so no need to pass a decoder to you function.
where you are returning SuccessHandler().checkSuccess(res); directly return the _responseString so it should be like this,
if (_responseCode == 200) {
final String _responseString = response.data;
log("post success response ------------
${_responseString}");
return SuccessHandler().checkSuccess(_responseString);
}
now try directly using ValidateEmailModel.fromJson on _responseString, you will get the data
In my project I get my json string which later on i tried to assign to it a jsonResponse variable but I got an error like : The argument type 'Response' can't be assigned to the parameter type 'String'.
Here's my code:
Future getMahalle() async {
BaseOptions options = new BaseOptions(
baseUrl: globals.PROD_URL,
connectTimeout: 5000,
receiveTimeout: 3000,
);
Dio dio = new Dio(options);
dio.options.headers["Authorization"] = "Bearer ${globals.USER_TOKEN}";
try {
var response =
await dio.get(globals.SELECT_URL); //'api/hizlirapor/selects'
final jsonResponse = jsonDecode(response); //Here is the error line
MahalleModel mahalleList =
MahalleModel.fromJson(jsonDecode(response.data['mahalle']));
return mahalleList;
} on DioError catch (e) {
debugPrint("ERRORR!!!!!!!!!!!!! ${e.error.toString()}");
return null;
}
}
I'm trying to implement this article for example and got stuck. Thanks for help!
You don't have to decode json returned since you are using dio, dio does that for you.
// if it's a single value than try this.
MahalleModel mahalleList = response.data.map<MahalleModel>((mahalle) => MahalleModel.fromJson(mahalle));
// if it's a list than try this.
List<MahalleModel> mahalleList = response.data['mahalle'].map<MahalleModel>((mahalle) => MahalleModel.fromJson(mahalle)).toList();
Hi I am try use mysql database in my flutter app...but till now fetch all data as string..what changes i have to done in my below code to received as data as my database...
in below code verify is a number and i want to received as number till time i received verify as string ....please help me ............
FetchJSON() async {
var Response = await http.get(
"http://192.168.42.107/my_payment/getdata.php",
headers: {"Accept": "application/json"},
);
if (Response.statusCode == 200) {
String responseBody = Response.body;
var responseJSON = json.decode(responseBody);
abc = responseJSON['username'];
verify = responseJSON['verified'];
setState(() {
print('UI Updated');
});
} else {
print('Something went wrong. \nResponse Code : ${Response.statusCode}');
}
}
So essentially you want "strongly typed" data for your http response, you have to define such data yourself. Normally people do something like this:
class MyData {
final String username;
final bool verified; // assume this should be a boolean
MyData.fromJson(dynamic json)
: username = json['username'],
verified = json['verified'] == 1; // assume you get back a number for verified
}
Then you can convert your responseJSON to MyData and carry on from there.
Using the Http module, this construction is used:
Http service:
let tokenUrl1 = this.apiUrl + 'login';
let headers1 = new Headers({'Content-Type': 'application/json'});
return this.http.post(tokenUrl1, JSON.stringify(model), {headers: headers1});
Call of the service:
this.loginService.sendCredential(this.model).subscribe(
data => {
// Next statement ... how to convert this for use in an HttpClint environment??
localStorage.setItem("token", JSON.parse(JSON.stringify(data))._body);
The nice HttpClient module parses the http content body with JSON returning an object. Nice!
How can the marked statement, "JSON.parse(JSON.stringify(data))._body)" be rewritten to fit nicely in the HttpClient environment?
You can manipulate the return type to string - that is sufficient for e.g. tokens:
let tokenUrl2 = this.apiUrl + 'users';
let getHeaders = new HttpHeaders({'Authorization':'Bearer '+token});
return this.httpClient.get(tokenUrl2, { observe: 'body', responseType: 'text', headers: getHeaders})
You can add observe in your header.
let tokenUrl1 = this.apiUrl + 'login';
let headers1 = new Headers({'Content-Type': 'application/json'});
return this.http.post(tokenUrl1, JSON.stringify(model), {
headers: headers1,
observe: 'response'
});
And
this.loginService.sendCredential(this.model).subscribe(
data => {
console.log(data.body);
You can use response as JSON object directly to get value like this.
this.loginService.sendCredential(this.model).subscribe(
data => {
let res = data.json();
let tokenValue = res['token']; // based on your json response...
localStorage.setItem("token", tokenValue);
}
And If you are using api-call with type then...(From Angular Doc)
showConfig() {
this.configService.getConfig()
.subscribe((data: Response) => {
// like data.xyz properties of 'Reponse' class
// here you can get values from Your 'Reponse' class directly instead of parsing as above.
});
}
Hope this helps.
Ask me if any query.