0

I was trying to create a function to make a GET with query parameters. I was dealing with the Mangadex API and was to send a parameter called 'manga' as an array. I created the code as follows:

Future<http.Response> getCoverArtResponse(String mangaID) async {
  var queryParameters = {
    'limit': '10',
    'manga': [mangaID] //Here
  };
  var unencodedPath = '/cover';
  var response = await http.get(
      Uri.https(authority, unencodedPath, queryParameters),
      headers: {HttpHeaders.contentTypeHeader: 'application/json'});
  return response;
}

However, the response was the following error:

{"result":"error","errors":[{"id":"9c346772-7b14-5982-b4b6-7b5888522762","status":400,"title":"validation_exception","detail":"Error validating \/manga: String value found, but an array is required","context":null}]}

How am I supposed to send the parameters? So far I have tried -

'manga': [mangaID]
'manga': '[$mangaID]'

None of them seem to work.

RikSantra
  • 81
  • 1
  • 10
  • It really depends on how their server expects arrays to be encoded in the query string. [It does not seem like there is a standard](https://stackoverflow.com/questions/6243051), and the Mangadex documentation doesn't seem to explicitly specify the format, but it does imply that they expect the key to be `manga[]`, not `manga`. Therefore try: `'manga[]': [mangaID]`. – jamesdlin Jul 31 '21 at 20:09

1 Answers1

1
import 'dart:async';
import 'package:wnetworking/wnetworking.dart';

class MangaDex {
  static const _base = 'https://api.mangadex.org';

  static FutureOr<void> _getter({required String url, required Function(JMap item, int idx) onItem}) async {
    await HttpReqService.getJson<JMap>(url)
      .then((response) {
        var results = response?['results'];
        if (results != null) {
          if (results is List) {
            var i = 0;
            results.forEach((manga) => onItem(manga, ++i));
          } else {
            print(response);
          }
        }
      });
  }

  static FutureOr<void> cover({int limit = 10, int offset=0, String? mangaId, String? coverId}) async {
    final mangas = mangaId != null ? '&manga[]=$mangaId' : '';
    final covers = coverId != null ? '&ids[]=$coverId' : '';
    final url = '$_base/cover?limit=$limit&offset=$offset$mangas$covers';

    await _getter(
      url: url, 
      onItem: (item, idx) {
        print('$idx) "${item['data']?['attributes']?['fileName']}"');
        print('   id: ${item['data']?['id']}\n');
      },
    );
  }
}

void main(List<String> args) async {
  await MangaDex.cover(mangaId: '32d76d19-8a05-4db0-9fc2-e0b0648fe9d0', limit: 2);
  print('\nJob done');
}

Result:

1) "f5873770-80a4-470e-a11c-63b709d87eb3.jpg"
   id: b6c7ce9c-e671-4f26-90b0-e592188e9cd6

2) "e9f926db-b469-48c4-8cc4-a8e523ad75ca.jpg"
   id: 00aae6e0-46bb-4f92-a82a-1c740789b704


Job done

Replace wnetworking package with http package, and JMap with Map<String, dynamic>

NOTE: MangaDex Documentation is lacking and misleading about how to correctly use its endpoints.

  • Yeah thank you very much that worked fine. However, this code seems interesting and I would like to know more about it, could you please explain how it works? Or could you please link an article to an example? That would be very kind of you, thanks. I understand the cover function but I don't understand what the _getter is doing. – RikSantra Aug 01 '21 at 04:44
  • It is simple, `_getter` method is responsible for calling GET requests, when getting a valid response (a List), it runs an operation (`onItem` function) per every item on that response. This method is useful for endpoints with things in common. – Ουιλιαμ Αρκευα Aug 01 '21 at 15:15