Не удается ввести объект json в функцию парсера Dart

Я возвращаю объект json из почтового запроса и хочу проанализировать его в модели дротика. Я уже создал модель дротика и fromJson функцию.

factory Did.fromJson(Map<String, dynamic> json) => Did(
      id: json['id'] as String,
      docHash: json['docHash'] as String,
      pubKey: json['pubKey'] as String,
      privKey: json['privKey'] as String,
      credential:
          Credential.fromJson(json['credential'] as Map<String, dynamic>),
      message: json['message'] as String,
      success: json['success'] as bool);

Это всего лишь отрывок из моей модели, но в той части, где я получил сообщение об ошибке The argument type 'dynamic' can't be assigned to the parameter type 'Map<String, dynamic>'. Я пытаюсь разобрать ответ на объект дротика после создания почтового запроса в репозитории блока:

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.data.toString());
  print(Did.fromJson(json));
  return Did.fromJson(json);
}

Декодированный объект json имеет тип dynamic, поэтому я не могу передать его в функцию Did.fromJson().
Как мне преобразовать ответ Dio, чтобы передать его в функцию fromJson?
Изменить:
Это моя модель, которая включает функцию fromJSON Did .dart
Редактировать 2:
Ответ на почтовый запрос Dio, который еще не проанализирован:
print(res)

{
  "id": "GbLnu9eCQ2sVBiKngNxts6NJMprxRczc63CKaZsiJsGT",
  "docHash": "PNSGTXSGODDBHRVWUTFIZUJT9UMPNM9MFBEMCQBYSIRQTDKXPVUCSPNBCXVNGIFEMWSBRUBYARZDA9999",
  "pubKey": "38aqV9FLAn9bXSPm388LcTronqZabEzpWKQpBZRcpPwP",
  "privKey": "A7cq3Z3eCN573wL4QDPR2UjwnDMML6deTf499RnN64zE",
  "credential": {
    "@context": "https://www.w3.org/2018/credentials/v1",
    "id": "http://example.edu/credentials/3732",
    "type": ["VerifiableCredential", "personalInformationCredential"],
    "credentialSubject": {
      "id": "did:iota:GbLnu9eCQ2sVBiKngNxts6NJMprxRczc63CKaZsiJsGT",
      "address": {
        "street": "awdwada",
        "city": "wdwad",
        "state": "awdad",
        "postalCode": "awdwad",
        "country": "wadawd"
      },
      "dateOfBirth": "2021-04-24T00:00:00.000",
      "email": "[email protected]",
      "name": { "first": "wadawd", "last": "awdawd" },
      "phoneNumber": "awdad",
      "sex": "male"
    },
    "issuer": "did:iota:A5STNhet1zgGbbnZCqniokcAdXbZZ2xcE6QWruQmctEs",
    "issuanceDate": "2021-04-24T15:02:41Z",
    "proof": {
      "type": "MerkleKeySignature2021",
      "verificationMethod": "#key-collection",
      "signatureValue": "3RypuceLDTQt1Anb9WdBj7ayPS91EdiYJ6ELPMChgocm.1117tuDcgbUJddXaLoFqvAh8WWeypGnCTuPCDggJ2cMk6AVyJAjHaaCgSmgaKsGa299TxVBqfypgqbjQx1gExf2kkD9XU8ViYhZRVm9dx5qELnVxcM2H5R5YmL6rLn3RR6SbiNSc7XG.22rTApWSHuzuZNFtN75KcsEVqhgzDG3WGoAxs2itVdy99DkKRSVkbCyhJgd1pgAQPPpnt65Sh3m733PsnY6QFojF"
    }
  },
  "message": "You have successfully created your digital identity, wadawd",
  "success": true
}

person JonasLevin    schedule 21.04.2021    source источник


Ответы (3)


Если вы уверены в типе, вам просто нужно сделать его явным, указав тип с помощью ключевого слова as (https://dart.dev/guides/language/language-tour#type-test-operators).

Например:

final json = jsonDecode(res.data.toString()) as Map<String, dynamic>;
print(Did.fromJson(json));
person Giovanni Londero    schedule 24.04.2021
comment
Теперь я получаю сообщение об ошибке: type 'List<dynamic>' is not a subtype of type 'List<String>' in type cast Значит, моя функция синтаксического анализатора, вероятно, неверна. - person JonasLevin; 24.04.2021
comment
Не могли бы вы предоставить образец смоделированного res для тестовых целей? С предоставленной вами моделью, возможно, я смогу воспроизвести проблему - person Giovanni Londero; 24.04.2021
comment
Я добавил ответ Dio на свой вопрос внизу. Я распечатал непроанализированный ответ. Я могу получить доступ к проанализированному ответу уже от Dio с помощью res.data. - person JonasLevin; 24.04.2021
comment
@JonasLevin круто, оставшаяся проблема, похоже, связана с typeof Credential.fromJson: вместо type: json['type'] as List<String> вам нужно будет сделать что-то вроде type: json['type'] is List ? (json['type'] as List).map((e) => e as String).toList() : [], (код можно улучшить, но должно дать представление) - person Giovanni Londero; 24.04.2021
comment
Я больше не получаю сообщение об ошибке после вашей реализации. Я буду продолжать работать с ним и буду реализовывать локальное сохранение данных. Спасибо за ответы. - person JonasLevin; 24.04.2021
comment
@JonasLevin FYI попробовал json_serializable (pub.dev/packages/json_serializable), чтобы увидеть, как они справились с аналогичным case, и оказалось, что результат type: (json['type'] as List<dynamic>).map((e) => e as String).toList(), так что это в основном то же самое решение, которое я предоставил; вы можете избежать is List проверки, если уверены, что она не равна нулю - person Giovanni Londero; 24.04.2021
comment
Да, это тоже работает, выглядит чище - person JonasLevin; 24.04.2021

Попробуйте изменить свой fromJson на такой:

id = json['id'];
docHash = json['docHash'];
pubKey = json['pubKey'];
privKey = json['privKey'];
credential = json['credential'] != null
    ? new Credential.fromJson(json['credential'])
    : null;
message = json['message'];
success = json['success'];

Изменить:

Я пытаюсь сделать запрос к вашему Api. Я создал модель, чтобы вы использовали ее вместо своей.

ссылка для скачивания: Модель данных

person Ahmad Darwesh    schedule 24.04.2021
comment
Я использовал этот пакет для создания своей модели, в нем уже реализована нулевая безопасность. Но модальное окно тоже довольно большое, 423 строки, поэтому я не хотел вставлять его в свой вопрос. Это моя модель. - person JonasLevin; 24.04.2021

Обратите внимание на тип res.data - Dio уже декодировал его в json, и вы можете передавать данные прямо в конструктор:

  if (res.statusCode == 200) {
    print(res.data.runtimeType); // _InternalLinkedHashMap<String, dynamic>
    return Did.fromJson(res.data);
  }

К вашему сведению, вы можете изменить тип данных ответа с помощью свойства responseType , Например:

  var res = await dio.post('http://did-backend.herokuapp.com/create',
      data: {
         // ...
      },
      options: Options(
        responseType: ResponseType.plain,
        headers: {
          // ...
        },
      ));
person Spatz    schedule 24.04.2021