How to turn part of the response from Dio into a variable in Flutter/Dart? - flutter

Using Dio, I make a specific request to the site:
final response = await Dio().get(
…
print(response); //Just to see my response
Here is the response from the console:
I/flutter ( 4594): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","Data":"11.5","App":"The Best App","Current":"98789fg43"}}]}
I am satisfied with the data. They are correct. For further work, I only need the recrNhzWnPdiSFaCs value. I want to pass it to a variable that will be used in another part of the code. How to do it?
Edit1.
Using var decodedString = json.decode(response.data.toString()); does not cause any errors in the code. But on startup, the following appears in the console:
I/flutter ( 4594): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","First":"11.5","App":"The Best App","Current":"98789fg43"}}]}
E/flutter ( 4594): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FormatException: Unexpected character (at character 2)
E/flutter(4594): {records: [{id: recrNhzWnPdiSFaCs, createdTime: 2022-07-28T15:45:23.000Z, f...
E/flutter ( 4594): ^
E/flutter ( 4594):
E/flutter ( 4594): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
E/flutter ( 4594): #1 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:913:48)
E/flutter ( 4594): #2 _parseJson (dart:convert-patch/convert_patch.dart:35:10)
E/flutter ( 4594): #3 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter ( 4594): #4 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter(4594): #5 _MainWidgetState.airtableFind(package:example/main.dart:214:32)
E/flutter ( 4594): <asynchronous suspension>
E/flutter ( 4594):
And here is the whole code in case I made a mistake somewhere:
//Airtable (find a record)
void airtableFind() async {
try {
final response = await Dio().get(
'https://api.airtable.com/v0/'+projectBase+'/'+recordName,
queryParameters: {
// 'filterByFormula': 'SEARCH("Cactus",{Name})' // Searches the value 'Cactus' in the {'Short description'} field.
'filterByFormula': 'SEARCH('+'"'+testName+'"'+',{Name})' // Searches the value 'Cactus' in the {'Short description'} field.
// 'filterByFormula': 'SEARCH('+testName+',{Name})' // Searches the value 'Cactus' in the {'Short description'} field.
},
options: Options(
contentType: 'Application/json',
headers: {
'Authorization': 'Bearer'+' '+apiKey,
'Accept': 'Application/json',
},
),
);
// TODO: Whatever you want to do with the response. A good practice is to transform it into models and than work with them
print(response);
// String fromString = response;
// String response1 = '{"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","Data":"11.5","App":"The Best App","Current":"98789fg43"}}]}';
var decodedString = json.decode(response.data.toString());
// final decodedJSON = json.decode(response.body);
// final decodedJSON = json.decode(utf8.decode(response.bodyBytes));
print(decodedString['records'][0]['id']);
String id = decodedString['records'][0]['id'];
} on DioError catch (e) {
// TODO: Error handling
if (e.response != null) {
// print(e.response.data);
print(e);
} else {
// print(e.request);
print(e.message);
}
}
}
Edit2. When I use final decodedString = json.decode(response.data); I see the following errors in the console:
I/flutter( 4289): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","First":"11.5","App":"The Best App","Current":"98789fg43"}}]}
E/flutter ( 4289): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
E/flutter(4289): #0 _MainWidgetState.airtableFind(package:example/main.dart:217:50)
E/flutter ( 4289): <asynchronous suspension>
When I use var decodedString = json.decode(response.data.toString()); the following errors appear in the console:
I/flutter( 4289): {"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","First":"11.5","App":"The Best App","Current":"98789fg43"}}]}
E/flutter ( 4289): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: FormatException: Unexpected character (at character 2)
E/flutter(4289): {records: [{id: recrNhzWnPdiSFaCs, createdTime: 2022-07-28T15:45:23.000Z, f...
E/flutter ( 4289): ^
E/flutter ( 4289):
E/flutter ( 4289): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1383:5)
E/flutter ( 4289): #1 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:913:48)
E/flutter ( 4289): #2 _parseJson (dart:convert-patch/convert_patch.dart:35:10)
E/flutter ( 4289): #3 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter ( 4289): #4 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter(4289): #5 _MainWidgetState.airtableFind(package:example/main.dart:217:32)
E/flutter ( 4289): <asynchronous suspension>

You can use json.decode to convert the response to a json value. Then you can fetch its values with respective keys like
String response = '{"records":[{"id":"recrNhzWnPdiSFaCs","createdTime":"2022-07-28T15:45:23.000Z","fields":{"Name":"Cactus ","Data":"11.5","App":"The Best App","Current":"98789fg43"}}]}';
var decodedString = json.decode(response);
print(decodedString['records'][0]['id']);
//Output : recrNhzWnPdiSFaCs
Don't miss to import
import 'dart:convert';

You can achieve your purpose by decoding your JSON.
final decodedJSON = json.decode(response.data);
, also if your response contains a UTF-8 encoding (has for example Persian characters), you can use:
final decodedJSON = json.decode(utf8.decode(response.bodyBytes));

dio body name is data so the decoding would be as following
final decodedJSON = json.decode(response.data);

Related

How to convert the type Future<List<T>> to <List<T>> in fultter?

everyone! I was developing e-commerce flutter app with doofinder APIs.
But I faced a thorny problem. I tried to get data from doofinder(it's just search service) API then present to screen. I added screen-shots.
Future<List<Product>> fetchProduct(query) async {
var response = await http.get(
Uri.parse(
'https://eu1-search.doofinder.com/5/search?hashid=30a5f&query=$query'),
// Send authorization headers to the backend.
headers: {'Authorization': 'c59dadc5d822ca2b134f170'},
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
print(jsonDecode(response.body)['results'].toList().runtimeType);
return jsonDecode(response.body)['results'].toList().cast<List<Product>>();
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load album');
}
}
then,
onChanged: (_) => EasyDebounce.debounce(
'tFMemberController',
const Duration(milliseconds: 800),
() {
isSearchStarted =
textController!.text.isNotEmpty &&
textController!.text.trim().length > 0;
print('isSearchStarted $isSearchStarted');
if (isSearchStarted) {
print('${textController!.text.trim()}');
searchedProducts =
fetchProduct(textController!.text)
as List<Product>;
print(searchedProducts);
}
setState(() {});
},
),
And this is error log.
E/flutter ( 5295): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Future<List<Product>>' is not a subtype of type 'List<Product>' in type cast
E/flutter ( 5295): #0 _SearchPageState.build.<anonymous closure>.<anonymous closure> (package:s4s_mobileapp/search/page_search.dart:151:41)
E/flutter ( 5295): #1 EasyDebounce.debounce.<anonymous closure> (package:easy_debounce/easy_debounce.dart:44:22)
E/flutter ( 5295): #2 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter ( 5295): #3 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
E/flutter ( 5295): #4 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
E/flutter ( 5295): #5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
E/flutter ( 5295):
I/flutter ( 5295): List<dynamic>
E/flutter ( 5295): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'CastList<dynamic, List<Product>>' is not a subtype of type 'FutureOr<List<Product>>'
E/flutter ( 5295): #0 fetchProduct (package:s4s_mobileapp/search/page_search.dart:41:58)
E/flutter ( 5295): <asynchronous suspension>
E/flutter ( 5295):
This makes me crazy.
I want you to take a closer look at the pictures below and find a suitable solution please.
Change
jsonDecode(response.body)['results'].toList().cast<List<Product>>();
to this:
jsonDecode(response.body)['results'].toList().cast<Product>();
The cast method already knows that you are working with lists and only wants to know the type of the elements, but not the type of the list itself.
EDIT: You also need to change:
searchedProducts = fetchProduct(textController!.text) as List<Product>;
to this:
searchedProducts = fetchProduct(textController!.text) as Future<List<Product>>;
You have to work with futures as your result is processed asynchronously. In the widget tree you have to use FutureBuilder which takes a future and builds your list as you want.

Error when decoding Uri.https, "Unhandled Exception: FormatException: Invalid character (at character 27)"

I'm trying to built weather app. I've searched weather API's, because I need make hourly and weekly weather forecast. I found this website https://www.visualcrossing.com/. I want to decode HTTP link (below in code) like this:
class DataServiceOneCall {
Future<WeatherResponseOnecall> getWeatherOneCall(String city) async {
//https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Olszowice?unitGroup=metric&key=QVDLJFCCQRM5296M7J975FP2W&contentType=json
final queryParameters = {
'q': city,
'unitGroup': 'metric',
'key': 'QVDLJFCCQRM5296M7J975FP2W',
'contentType': 'json',
};
final uri = Uri.https(
'weather.visualcrossing.com/VisualCrossingWebServices',
'/rest/services/timeline,',
queryParameters);
final response_onecall = await http.get(uri);
print(response_onecall.body);
final json = jsonDecode(response_onecall.body);
return WeatherResponseOnecall.fromJson(json);
}
}
And I've got error thrown like this.
E/flutter (11332): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FormatException: Invalid character (at character 27)
E/flutter (11332): weather.visualcrossing.com/VisualCrossingWebServices
E/flutter (11332): ^
E/flutter (11332):
E/flutter (11332): #0 _Uri._fail (dart:core/uri.dart:1754:5)
E/flutter (11332): #1 _Uri._normalizeRegName (dart:core/uri.dart:2252:9)
E/flutter (11332): #2 _Uri._makeHost (dart:core/uri.dart:2113:12)
E/flutter (11332): #3 new _Uri (dart:core/uri.dart:1640:12)
E/flutter (11332): #4 _Uri._makeHttpUri (dart:core/uri.dart:1813:12)
E/flutter (11332): #5 new _Uri.https (dart:core/uri.dart:1678:12)
E/flutter (11332): #6 DataServiceOneCall.getWeatherOneCall package:weather_app/data_service/data_service_onecall.dart:18
Thanks for help.
I rewrite this code like this and it works.
final uri = Uri.https(
'weather.visualcrossing.com',
'/VisualCrossingWebServices/rest/services/timeline/${city}?',
queryParameters);
V after slash would be small.
final uri = Uri.https(
'weather.visualcrossing.com/visualCrossingWebServices',
'/rest/services/timeline,',

Flutter get return empty body but it is not empty

as I wrote in the title I'm trying to obtain data from a server but the method http.get(Uri.parse(url)) returns empty body and od course the error caused by trying to decode an empty body,
But if I copy paste the url used before I can see the json content. How is it possible?
The function I'm using is:
Future getData ( ) async {
String url = 'http://www.viaggiatreno.it/viaggiatrenonew/resteasy/viaggiatreno/andamentoTreno/...';
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 204) {
var data = response.body;
print("data are : $data");
return jsonDecode(data);
} else {
print("unable to load data");
}
}
This is a little portion of what I should see with this command: print("data are : $data");
{
"tipoTreno":"PG",
"orientamento":"B",
"codiceCliente":1,
"fermateSoppresse":[
],
"dataPartenza":null,
"fermate":[
{
"orientamento":"B",
"kcNumTreno":null,
"stazione":"VENEZIA SANTA LUCIA",
"id":"S02593",
"listaCorrispondenze":null,
"programmata":1646663160000,
"programmataZero":null,
"effettiva":1646663160000,
"ritardo":0,
"partenzaTeoricaZero":1646663160000,
"arrivoTeoricoZero":null,
"partenza_teorica":1646663160000,
"arrivo_teorico":null,
"isNextChanged":false,
"partenzaReale":1646663160000,
"arrivoReale":null,
"ritardoPartenza":0,
"ritardoArrivo":0,
"\"pro ...........}"
so as you can see the body is what you want but not empty, and it is in json format.
Can anyone help me? I can't solve this issue.
Output is:
I/flutter (3177): data are:
E/flutter ( 3177): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: FormatException: Unexpected end of input (at character 1)
E/flutter ( 3177):
E/flutter ( 3177): ^
E/flutter ( 3177):
E/flutter ( 3177): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1405:5)
E/flutter ( 3177): #1 _ChunkedJsonParser.close (dart:convert-patch/convert_patch.dart:523:7)
E/flutter ( 3177): #2 _parseJson (dart:convert-patch/convert_patch.dart:41:10)
E/flutter ( 3177): #3 JsonDecoder.convert (dart:convert/json.dart:612:36)
E/flutter ( 3177): #4 JsonCodec.decode (dart:convert/json.dart:216:41)
E/flutter ( 3177): #5 jsonDecode (dart:convert/json.dart:155:10)
E/flutter ( 3177): #6 NetworkHelper.ottieniTutteInfo (package:agenda_ferrovia/utilities/networkConnection.dart:36:14)
E/flutter ( 3177): <asynchronous suspension>
E/flutter ( 3177): #7 _ServizioUIAggiungiTrenoState.build.ottieniOrigine (package:agenda_ferrovia/screens/servizioUI/servizioUI_singolo.dart:110:33)
E/flutter ( 3177): <asynchronous suspension>
E/flutter ( 3177): #8 _ServizioUIAggiungiTrenoState.build.<anonymous closure> (package:agenda_ferrovia/screens/servizioUI/servizioUI_singolo.dart:231:23)
E/flutter ( 3177): <asynchronous suspension>
E/flutter ( 3177):
Thanks all for the support! I've found the issue!
Some part of the 'url's String' comes from another call.
Inside a variable there was the "hidden chars" \n. That was the cause of the issue -.-
I've solved removing all chars except letters before save into variable used for the 'url'.
I hope that my English was clear enough to understand.
Bye!

Api Request using Http request for get method. but don't know actual problem in Flutter

I am new in flutter and learning api request. I make a request for get method. but it shows error! i can't receive any data!
In Postman, it works fine and data comes properly!
This api and token is only for test porpuse! so, don't worry!
Api request
Future fetchAlbum() async {
final token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjI4OTksImlzcyI6Imh0dHBzOi8vcG9ydGFsLWFwaS5qb21ha2hhdGEuY29tL2FwaS9hdXRoL2xvZ2luIiwiaWF0IjoxNjMxMjUxNjYwLCJleHAiOjE2MzEzMzgwNjAsIm5iZiI6MTYzMTI1MTY2MCwianRpIjoiNlFEUTZCYnBMT0JhdUJoaSJ9.jAY_2nYxjgsIvXZY5vn0vAr_pwF6UBYbSGZ8wqD0YPQ';
final response = await http.get(
Uri.parse('https://portal-api.jomakhata.com/api/getLeaveDetails?token=${token}'),
// Send authorization headers to the backend.
);
final responseJson = jsonDecode(response.body);
if(response.statusCode==200){
print("ok");
print(responseJson);
}
else{
print("error!");
}
return responseJson;
}
Error in Console
D/EGL_emulation(19932): app_time_stats: avg=14700.05ms min=577.55ms max=28822.55ms count=2
E/flutter (19932): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: FormatException: Unexpected character (at character 335)
E/flutter (19932): ...ning":14}],"fiscalYear":"2021-2022"}{"message":"SQLSTATE[22001]: String ...
E/flutter (19932): ^
E/flutter (19932):
E/flutter (19932): #0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1404:5)
E/flutter (19932): #1 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:869:48)
E/flutter (19932): #2 _parseJson (dart:convert-patch/convert_patch.dart:40:10)
E/flutter (19932): #3 JsonDecoder.convert (dart:convert/json.dart:506:36)
E/flutter (19932): #4 JsonCodec.decode (dart:convert/json.dart:157:41)
E/flutter (19932): #5 jsonDecode (dart:convert/json.dart:96:10)
E/flutter (19932): #6 fetchAlbum (package:test_list/main.dart:51:24)
E/flutter (19932): <asynchronous suspension>
E/flutter (19932):
There is an error in the API endpoint you are calling, more precisely there is an SQL error SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'url' at row 1.
Because of this, an error message is inserted into the JSON output, like this:
}{
"message": ...
This is not a problem for Postman to display, but as a result you get an invalid JSON, there should be a , between { and }.
So when you try to decode it in Flutter, you will get an error, because conversion fails: Unhandled Exception: FormatException: Unexpected character.

The getter 'data' was called on null in response

I expext response.data to be when i got an error 422, like
{
"message": "You can NOT add a penalty!"
}
but i have an error The getter 'data' was called on null.
Future transferCoinsToUser(
String apiToken, String recipientBill, int coin) async {
Response response;
try {
response = await _dio.post(apiEndpoint + "bills/transfer",
options: Options(headers: {"Authorization": apiToken}),
data: {"recipient_bill": recipientBill, "coin": coin});
if(response.statusCode == 200){
print('status cod ' + response.statusCode.toString());
print('response bady ' + response.data.toString());//{message: completed successfully.}
}
} on DioError catch (error) {
print(error);
print(response.data);// The getter 'data' was called on null.
return null;
}
}
my stack trace
NoSuchMethodError: The getter 'data' was called on null.
I/flutter ( 7462): Receiver: null
I/flutter ( 7462): Tried calling: data
I/flutter ( 7462): NoSuchMethodError: The getter 'data' was called on null.
I/flutter ( 7462): Receiver: null
I/flutter ( 7462): Tried calling: data
I/flutter ( 7462): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
I/flutter ( 7462): #1 ApiProvider.transCoinToUser (package:no_fine/data/api_provider.dart:104:22)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #2 TransferRepositoryImpl.transCoinToUser (package:no_fine/data/repository/transfer_repo.dart:37:20)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #3 TransferBloc._mapTransferCoinsToUserToState (package:no_fine/bloc/auth/translations_bloc/translations_bloc.dart:42:33)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #4 TransferBloc.mapEventToState (package:no_fine/bloc/auth/translations_bloc/translations_bloc.dart:26:14)
I/flutter ( 7462): <asynchronous suspension>
I/flutter ( 7462): #5 Bloc._bindEventsToStates.<anonymous closure> (package:bloc/src/bloc.dart:232:20)
I/flutter ( 7462): #6 Stream.asyncExpand.<anonymous closure>.<anonymous closure> (dart:async/stream.dart:644:30)
I/flutter ( 7462): #7 _rootRunUnary (dart:async/zone.dart:1198:47)
I/flutter ( 7462): #8 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
I/flutter ( 7462): #9 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
I/flutter ( 7462): #10 _BufferingStreamSubscription._sendData (dart:a
response might be null. You are calling .data on null hence the error. Try
print(response?.data)
or check
if(response != null) print(response.data);
You can't access the Response object, when you have an error. Instead, Please use below code:
on DioError catch (error) {
print(error);
print(error.response.data);// Here you will find the error response in error object
return null;
}
You can check your request host. In Android device you can not use the request host like "localhost" or "127.0.0.1" directly because this is the Android device's host and this is not your API host.You should use your API host's IP which like "http://192.168.50.123/request?foo=bar".