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

#dart #bloc #flutter-bloc

Вопрос:

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

 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>' . Я пытаюсь проанализировать ответ на объект dart после создания запроса post в репозитории блоков:

 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 post, который еще не проанализирован:
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": "awdadawd@adwad.co",
      "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
}
 

Ответ №1:

Если вы уверены в типе, вам просто нужно указать его явно, введя 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));
 

Комментарии:

1. Теперь я получаю ошибку: type 'List<dynamic>' is not a subtype of type 'List<String>' in type cast так что моя функция синтаксического анализа, вероятно, неверна.

2. Не могли бы вы предоставить образец, высмеянный res для целей тестирования? С помощью предоставленной вами модели, возможно, я смогу воспроизвести проблему

3. Я добавил ответ Dio на свой вопрос внизу. Я напечатал не проанализированный ответ. Я уже могу получить доступ к проанализированному ответу от Dio с помощью res.data.

4. @JonasLevin круто, остающаяся проблема, похоже, связана с type учетными данными.FromJSON: вместо type: json['type'] as List<String> этого вам придется сделать что-то вроде type: json['type'] is List ? (json['type'] as List).map((e) => e as String).toList() : [], (код можно улучшить, но он должен дать представление)

5. Я больше не получаю ошибок после вашей реализации. Я буду продолжать работать с ним и реализовывать локальное сохранение данных. Спасибо за ваши ответы.

Ответ №2:

Попробуй изменить себя 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, я сгенерировал модель для вас, используйте ее вместо вашей

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

Комментарии:

1. Я использовал этот пакет для создания своей модели, в нем уже реализована нулевая безопасность. Но модальный также довольно большой, 423 строки, поэтому я не хотел вставлять его в свой вопрос. Это моя модель

Ответ №3:

Обратите внимание на 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: {
          // ...
        },
      ));