Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a json from a Dart http call / How to consume a stream entirely?

Tags:

json

http

dart

Here's my code that should return a json. I adapted this code from here https://github.com/flutter/flutter/issues/15110

  Stream _defaultReturn(HttpClientResponse httpClientResponse) {
    Stream response = httpClientResponse.
                      transform(utf8.decoder).
                      transform(json.decoder).
                      asyncMap((json) => jsonDecode(json));
    return response;
  }

  Future<dynamic> get(String endpoint) async {
    HttpClientRequest httpClientRequest =
        await httpClient.getUrl(Uri.parse(_url + endpoint));
    _addCookies(httpClientRequest);
    final HttpClientResponse httpClientResponse =
        await httpClientRequest.close();
    return _defaultReturn(httpClientResponse);
  }

I've put a return type of Stream into _defaultReturn because intellisense told me that giant thing returned me a Stream. I would actually want to receive a json (which should be a map). I think I migth consume or subscribe to this stream to get something useful. However, I don't see parsin json as stream as being useful. Don't I need the entire json before parsing? Shouldn't I simply accumulate everything into a String and then simply call jsonDecode?

Which is the most efficient way of returning a json from an http call? And how to do it?

like image 231
Guerlando OCs Avatar asked Feb 14 '20 05:02

Guerlando OCs


2 Answers

json.decoder will listen source stream and always transform its content to just one Object, so you can just return it with stream's .first:

Future<Object> get(String endpoint) async {
  var httpClientRequest = await httpClient.getUrl(Uri.parse(_url + endpoint));
  _addCookies(httpClientRequest);
  final httpClientResponse = await httpClientRequest.close();
  return httpClientResponse
           .transform(utf8.decoder)
           .transform(json.decoder)
           .first;
}

Then you can use it like this:

var jsonObject = await myHttpClient.get(myEndpoint);
like image 90
Styx Avatar answered Oct 19 '22 00:10

Styx


There is a package named JSON_Serializable that you could make use of. Generate your object class, and you could map your HTTP return to the class.

final response = await http.get(url, headers: await setHeaders());
dynamic parsed = jsonDecode(await response.body);
YourItemsList = List<YourItems>.from(
    parsed['data'].map((i) => YourItems.fromJson(i)));

Your class generation will include both functions below:

  factory YourItemsList.fromJson(Map<dynamic, dynamic> json) =>
  _$YourItemsListFromJson(json);

  Map<String, dynamic> toJson() => _$YourItemsListToJson(this);
like image 21
xion Avatar answered Oct 19 '22 02:10

xion