gpt4 book ai didi

flutter - 类型 'List'不是 'Map'类型的子类型

转载 作者:行者123 更新时间:2023-12-03 04:54:41 26 4
gpt4 key购买 nike

我正在开发一个依赖API REST调用的Flutter应用程序.API的响应有点复杂。
调用API(例如api / products)时,我可以从日志中看到响应:
但是我有这个错误:类型'List <动态>'不是类型'Map <字符串,动态>'的子类型
我在互联网上看到了所有问题/答案,没有任何结果。
我已经尝试过使用像https://my-json-server.typicode.com/typicode/demo/posts这样的简单RestAPI,它可以工作。
但这不是我的情况
API响应示例:

[
{
"id":1,
"tenant":{
"id":1,
"code":"company",
"name":"company"
},
"type":{
"code":"activity",
"name":"Activité"
},
"subType":{
"code":"ticket",
"name":"Ticket"
},
"inventoryType":{
"code":"external_source",
"name":"Source externe"
},
"externalReference":"CAL6970",
"externalSystem":{
"code":"koedia",
"name":"Koedia"
},
"active":true,
"durationDays":12,
"durationNights":14,
"durationHours":9,
"durationMinutes":10,
"supplier":{
"id":1,
"tenant":{
"id":1,
"code":"company",
"name":"company"
},
"name":"Jancarthier"
},
"group":null,
"subGroup":null,
"name":"Hôtel Koulnoué Village",
"translations":[
{
"id":1,
"name":"Hôtel Koulnoué Village",
"locale":"fr"
},
{
"id":24,
"name":"Hôtel Koulnoué Village",
"locale":"en"
}
],
"vatPercentage":"0.00",
"longitude":null,
"latitude":null,
"departureTime":null,
"arrivalTime":null,
"arrivalDayPlus":1,
"stars":4,
"localities":[
{
"id":41,
"locality":{
"id":34,
"code":"ARM",
"name":"Armenia"
},
"role":{
"code":"stop",
"name":"Escale"
}
},
{
"id":49,
"locality":{
"id":55,
"code":"hossegor",
"name":"Hossegor"
},
"role":{
"code":"drop_off",
"name":"Retour"
}
},
{
"id":50,
"locality":{
"id":55,
"code":"hossegor",
"name":"Hossegor"
},
"role":{
"code":"localisation",
"name":"Localisation"
}
}
]
}
]

堆栈跟踪 :
I/flutter ( 2865): type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'


[更新] :返回ProductsResponse.fromJson(response)而不是响应
产品库
import 'dart:async';
import 'package:day_experience/models/product/ProductResponse.dart';
import 'package:day_experience/networking/ApiProvider.dart';

class ProductRepository {
ApiProvider _provider = ApiProvider();

Future<ProductsResponse> fetchProducts() async {

final response = await _provider.getFromApi("products");
// here line 11 where exception is thrown
return ProductsResponse.fromJson(response);
}


}

产品集团:
import 'dart:async';

import 'package:day_experience/models/product/ProductResponse.dart';

import 'package:day_experience/networking/Response.dart';
import 'package:day_experience/repository/ProductRepository.dart';


class ProductBloc {
ProductRepository _productRepository;
StreamController _productListController;
bool _isStreaming;
StreamSink<Response<ProductsResponse>> get productListSink =>
_productListController.sink;


Stream<Response<ProductsResponse>> get productListStream =>
_productListController.stream;

ProductBloc() {
_productListController = StreamController<Response<ProductsResponse>>();
_productRepository = ProductRepository();
_isStreaming = true;
fetchProducts();

}

fetchProducts() async {
productListSink.add(Response.loading('Getting Products.'));
try {
ProductsResponse productsResponse =
await _productRepository.fetchProducts();
if (_isStreaming) productListSink.add(Response.completed(productsResponse));
} catch (e) {
if (_isStreaming) productListSink.add(Response.error(e.toString()));
print(e);
}
}

dispose() {
_isStreaming = false;
_productListController?.close();
}
}

回应:
class Response<T> {
Status status;
T data;
String message;

Response.loading(this.message) : status = Status.LOADING;
Response.completed(this.data) : status = Status.COMPLETED;
Response.error(this.message) : status = Status.ERROR;

@override
String toString() {
return "Status : $status \n Message : $message \n Data : $data";
}
}

enum Status { LOADING, COMPLETED, ERROR }

ApiProvider:
import 'package:day_experience/networking/CustomException.dart';
import 'package:http/http.dart' as http;
import 'dart:io';
import 'dart:convert';
import 'dart:async';

class ApiProvider {

final String _baseApiUrl = "URL_API/";

Future<dynamic> getFromApi(String url) async {
var responseJson;
try {
final response = await http.get(Uri.encodeFull(_baseApiUrl + url),headers:{"Accept":"application/json"} );
print(response);
responseJson = _response(response);
} on SocketException {
throw FetchDataException('No Internet connection');
}
return responseJson;
}

dynamic _response(http.Response response) {
switch (response.statusCode) {
case 200:
var responseJson = json.decode(response.body);

print(responseJson);
return responseJson;
case 400:
throw BadRequestException(response.body.toString());
case 401:

case 403:
throw UnauthorisedException(response.body.toString());
case 500:

default:
throw FetchDataException(
'Error occured while Communication with Server with StatusCode : ${response.statusCode}');
}
}
}

型号:产品响应
import 'ExternalSystem.dart';
import './InventoryType.dart';
import './Localities.dart';
import 'SubType.dart';
import 'Supplier.dart';
import 'Tenant.dart';
import './Translation.dart';
import './Type.dart';

class ProductsResponse {
final int id;
final Tenant tenant;
final Type type;
final SubType subType;
final InventoryType inventoryType;
final String externalReference;
final ExternalSystem externalSystem;
final bool active;
final int durationDays;
final int durationNights;
final int durationHours;
final int durationMinutes;
final Supplier supplier;
final String name;
final List<Translation> translations;
final String vatPercentage;
final int arrivalDayPlus;
final int stars;
final List<Localities> localities;
final String group;
final String subGroup;
final double longitude;
final double latitude;
final String departureTime;
final String arrivalTime;

ProductsResponse({this.id, this.tenant , this.type, this.subType, this.inventoryType, this.externalReference, this.externalSystem, this.active, this.durationDays, this.durationNights, this.durationHours, this.durationMinutes, this.supplier, this.name, this.translations, this.vatPercentage, this.arrivalDayPlus, this.stars, this.localities, this.group, this.subGroup, this.longitude, this.latitude, this.departureTime, this.arrivalTime});

factory ProductsResponse.fromJson(Map<String, dynamic> json) {
return ProductsResponse(
id: json['id'],
tenant: json['tenant'] != null ? Tenant.fromJson(json['tenant']) : null,
type: json['type'] != null ? Type.fromJson(json['type']) : null,
subType: json['subType'] != null ? SubType.fromJson(json['subType']) : null,
inventoryType: json['inventoryType'] != null ? InventoryType.fromJson(json['inventoryType']) : null,
externalReference: json['externalReference'],
externalSystem: json['externalSystem'] != null ? ExternalSystem.fromJson(json['externalSystem']) : null,
active: json['active']?json['active']:null,
durationDays: json['durationDays']?json['durationDays']:null,
durationNights: json['durationNights']?json['durationNights']:null,
durationHours: json['durationHours']?json['durationHours']:null,
durationMinutes: json['durationMinutes']?json['durationMinutes']:null,
supplier: json['supplier'] != null ? Supplier.fromJson(json['supplier']) : null,
name: json['name']?json['name']:null,
translations: json['translations'] != null ? (json['translations'] as List).map((i) => Translation.fromJson(i)).toList() : null,
vatPercentage: json['vatPercentage']?json['vatPercentage']:null,
arrivalDayPlus: json['arrivalDayPlus']?json['arrivalDayPlus']:null,
stars: json['stars']?json['stars']:null,
localities: json['localities'] != null ? (json['localities'] as List).map((i) => Localities.fromJson(i)).toList() : null,
group: json['group'] != null ? json['group'] : null,
subGroup: json['subGroup'] != null ? json['subGroup'] : null,
longitude: json['longitude'] != null ? json['longitude'] : null,
latitude: json['latitude'] != null ? json['latitude'] : null,
departureTime: json['departureTime'] != null ? json['departureTime'] : null,
arrivalTime: json['arrivalTime'] != null ? json['arrivalTime'] : null,
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['externalReference'] = this.externalReference;
data['active'] = this.active;
data['durationDays'] = this.durationDays;
data['durationNights'] = this.durationNights;
data['durationHours'] = this.durationHours;
data['durationMinutes'] = this.durationMinutes;
data['name'] = this.name;
data['vatPercentage'] = this.vatPercentage;
data['arrivalDayPlus'] = this.arrivalDayPlus;
data['stars'] = this.stars;
if (this.tenant != null) {
data['tenant'] = this.tenant.toJson();
}
if (this.type != null) {
data['type'] = this.type.toJson();
}
if (this.subType != null) {
data['subType'] = this.subType.toJson();
}
if (this.inventoryType != null) {
data['inventoryType'] = this.inventoryType.toJson();
}
if (this.externalSystem != null) {
data['externalSystem'] = this.externalSystem.toJson();
}
if (this.supplier != null) {
data['supplier'] = this.supplier.toJson();
}
if (this.translations != null) {
data['translations'] = this.translations.map((v) => v.toJson()).toList();
}
if (this.localities != null) {
data['localities'] = this.localities.map((v) => v.toJson()).toList();
}
if (this.group != null) {
data['group'] = this.group;
}
if (this.subGroup != null) {
data['subGroup'] = this.subGroup;
}
if (this.longitude != null) {
data['longitude'] = this.longitude;
}
if (this.latitude != null) {
data['latitude'] = this.latitude;
}
if (this.departureTime != null) {
data['departureTime'] = this.departureTime;
}
if (this.arrivalTime != null) {
data['arrivalTime'] = this.arrivalTime;
}
print(data);

return data;
}
}

[更新] :删除了ProductsRepository(仅应通过bloc访问)
产品浏览
import 'package:day_experience/blocs/ProductBloc.dart';
import 'package:day_experience/models/product/ProductResponse.dart';
import 'package:day_experience/networking/Response.dart';
import 'package:day_experience/repository/ProductRepository.dart';
import 'package:day_experience/view/widget/Loading.dart';
import 'package:day_experience/view/widget/ProductList.dart';
import 'package:flutter/material.dart';
import 'package:day_experience/view/widget/Error.dart';


class ProductView extends StatefulWidget {
@override
_ProductViewState createState() => _ProductViewState();
}

class _ProductViewState extends State<ProductView> {
ProductBloc _bloc = new ProductBloc();

@override
void initState() {
super.initState();
_bloc.fetchProducts();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
automaticallyImplyLeading: false,
title: Text('Products',
style: TextStyle(color: Colors.white, fontSize: 20)),
backgroundColor: Color(0xFF333333),
),
backgroundColor: Color(0xFF333333),
body: RefreshIndicator(
onRefresh: () => _bloc.fetchProducts(),
child: StreamBuilder<Response<ProductsResponse>>(
stream: _bloc.productListStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
switch (snapshot.data.status) {
case Status.LOADING:
return Loading(loadingMessage: snapshot.data.message);
break;
case Status.COMPLETED:
return ProductList(productList:snapshot.data.data);
break;
case Status.ERROR:
return Error(
errorMessage: snapshot.data.message,
onRetryPressed: () => _bloc.fetchProducts(),
);
break;
}
}
return Container();
},
),
),
);
}


}



承租人示例其他逻辑相同(Translation,Type,SubType ..)
class Tenant {
final int id;
final String code;
final String name;

Tenant({this.id, this.code, this.name});

factory Tenant.fromJson(Map<String, dynamic> json) {
return Tenant(
id: json['id'],
code: json['code'],
name: json['name'],
);
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['code'] = this.code;
data['name'] = this.name;
return data;
}
}

最佳答案

您可以在下面复制粘贴运行完整代码
因为您的json字符串产生的是List<ProductResponse>而不是ProductResponse在您的代码中,您可以直接将response.body返回为String并使用productsResponseFromJson进行解析

程式码片段

List<ProductsResponse> productsResponseFromJson(String str) =>
List<ProductsResponse>.from(
json.decode(str).map((x) => ProductsResponse.fromJson(x)));

Future<List<ProductsResponse>> fetchProducts() async {
ApiProvider _provider = ApiProvider();
String response = await _provider.getFromApi("products");
// here line 11 where exception is thrown
return productsResponseFromJson(response);
//return ProductsResponse.fromJson(response);
}

Future<String> getFromApi(String url) async {

String _response(http.Response response) {
switch (response.statusCode) {
case 200:
print(response.body);
//var responseJson = jsonDecode(response.body);

//print(responseJson);
return response.body;

工作演示

enter image description here

完整的代码
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// To parse this JSON data, do
//
// final productsResponse = productsResponseFromJson(jsonString);

import 'dart:convert';

List<ProductsResponse> productsResponseFromJson(String str) =>
List<ProductsResponse>.from(
json.decode(str).map((x) => ProductsResponse.fromJson(x)));

String productsResponseToJson(List<ProductsResponse> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class ProductsResponse {
int id;
Tenant tenant;
ExternalSystem type;
ExternalSystem subType;
ExternalSystem inventoryType;
String externalReference;
ExternalSystem externalSystem;
bool active;
int durationDays;
int durationNights;
int durationHours;
int durationMinutes;
Supplier supplier;
dynamic group;
dynamic subGroup;
String name;
List<Translation> translations;
String vatPercentage;
dynamic longitude;
dynamic latitude;
dynamic departureTime;
dynamic arrivalTime;
int arrivalDayPlus;
int stars;
List<Locality> localities;

ProductsResponse({
this.id,
this.tenant,
this.type,
this.subType,
this.inventoryType,
this.externalReference,
this.externalSystem,
this.active,
this.durationDays,
this.durationNights,
this.durationHours,
this.durationMinutes,
this.supplier,
this.group,
this.subGroup,
this.name,
this.translations,
this.vatPercentage,
this.longitude,
this.latitude,
this.departureTime,
this.arrivalTime,
this.arrivalDayPlus,
this.stars,
this.localities,
});

factory ProductsResponse.fromJson(Map<String, dynamic> json) =>
ProductsResponse(
id: json["id"],
tenant: Tenant.fromJson(json["tenant"]),
type: ExternalSystem.fromJson(json["type"]),
subType: ExternalSystem.fromJson(json["subType"]),
inventoryType: ExternalSystem.fromJson(json["inventoryType"]),
externalReference: json["externalReference"],
externalSystem: ExternalSystem.fromJson(json["externalSystem"]),
active: json["active"],
durationDays: json["durationDays"],
durationNights: json["durationNights"],
durationHours: json["durationHours"],
durationMinutes: json["durationMinutes"],
supplier: Supplier.fromJson(json["supplier"]),
group: json["group"],
subGroup: json["subGroup"],
name: json["name"],
translations: List<Translation>.from(
json["translations"].map((x) => Translation.fromJson(x))),
vatPercentage: json["vatPercentage"],
longitude: json["longitude"],
latitude: json["latitude"],
departureTime: json["departureTime"],
arrivalTime: json["arrivalTime"],
arrivalDayPlus: json["arrivalDayPlus"],
stars: json["stars"],
localities: List<Locality>.from(
json["localities"].map((x) => Locality.fromJson(x))),
);

Map<String, dynamic> toJson() => {
"id": id,
"tenant": tenant.toJson(),
"type": type.toJson(),
"subType": subType.toJson(),
"inventoryType": inventoryType.toJson(),
"externalReference": externalReference,
"externalSystem": externalSystem.toJson(),
"active": active,
"durationDays": durationDays,
"durationNights": durationNights,
"durationHours": durationHours,
"durationMinutes": durationMinutes,
"supplier": supplier.toJson(),
"group": group,
"subGroup": subGroup,
"name": name,
"translations": List<dynamic>.from(translations.map((x) => x.toJson())),
"vatPercentage": vatPercentage,
"longitude": longitude,
"latitude": latitude,
"departureTime": departureTime,
"arrivalTime": arrivalTime,
"arrivalDayPlus": arrivalDayPlus,
"stars": stars,
"localities": List<dynamic>.from(localities.map((x) => x.toJson())),
};
}

class ExternalSystem {
String code;
String name;

ExternalSystem({
this.code,
this.name,
});

factory ExternalSystem.fromJson(Map<String, dynamic> json) => ExternalSystem(
code: json["code"],
name: json["name"],
);

Map<String, dynamic> toJson() => {
"code": code,
"name": name,
};
}

class Locality {
int id;
Tenant locality;
ExternalSystem role;

Locality({
this.id,
this.locality,
this.role,
});

factory Locality.fromJson(Map<String, dynamic> json) => Locality(
id: json["id"],
locality: Tenant.fromJson(json["locality"]),
role: ExternalSystem.fromJson(json["role"]),
);

Map<String, dynamic> toJson() => {
"id": id,
"locality": locality.toJson(),
"role": role.toJson(),
};
}

class Tenant {
int id;
String code;
String name;

Tenant({
this.id,
this.code,
this.name,
});

factory Tenant.fromJson(Map<String, dynamic> json) => Tenant(
id: json["id"],
code: json["code"],
name: json["name"],
);

Map<String, dynamic> toJson() => {
"id": id,
"code": code,
"name": name,
};
}

class Supplier {
int id;
Tenant tenant;
String name;

Supplier({
this.id,
this.tenant,
this.name,
});

factory Supplier.fromJson(Map<String, dynamic> json) => Supplier(
id: json["id"],
tenant: Tenant.fromJson(json["tenant"]),
name: json["name"],
);

Map<String, dynamic> toJson() => {
"id": id,
"tenant": tenant.toJson(),
"name": name,
};
}

class Translation {
int id;
String name;
String locale;

Translation({
this.id,
this.name,
this.locale,
});

factory Translation.fromJson(Map<String, dynamic> json) => Translation(
id: json["id"],
name: json["name"],
locale: json["locale"],
);

Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"locale": locale,
};
}

void main() {
runApp(MyApp());
}

Future<List<ProductsResponse>> fetchProducts() async {
ApiProvider _provider = ApiProvider();
String response = await _provider.getFromApi("products");
// here line 11 where exception is thrown
return productsResponseFromJson(response);
//return ProductsResponse.fromJson(response);
}

class ApiProvider {
Future<String> getFromApi(String url) async {
var responseJson;
try {
//final response = await http.get(Uri.encodeFull(_baseApiUrl + url),headers:{"Accept":"application/json"} );
String jsonString = '''
[
{
"id":1,
"tenant":{
"id":1,
"code":"company",
"name":"company"
},
"type":{
"code":"activity",
"name":"Activité"
},
"subType":{
"code":"ticket",
"name":"Ticket"
},
"inventoryType":{
"code":"external_source",
"name":"Source externe"
},
"externalReference":"CAL6970",
"externalSystem":{
"code":"koedia",
"name":"Koedia"
},
"active":true,
"durationDays":12,
"durationNights":14,
"durationHours":9,
"durationMinutes":10,
"supplier":{
"id":1,
"tenant":{
"id":1,
"code":"company",
"name":"company"
},
"name":"Jancarthier"
},
"group":null,
"subGroup":null,
"name":"Hôtel Koulnoué Village",
"translations":[
{
"id":1,
"name":"Hôtel Koulnoué Village",
"locale":"fr"
},
{
"id":24,
"name":"Hôtel Koulnoué Village",
"locale":"en"
}
],
"vatPercentage":"0.00",
"longitude":null,
"latitude":null,
"departureTime":null,
"arrivalTime":null,
"arrivalDayPlus":1,
"stars":4,
"localities":[
{
"id":41,
"locality":{
"id":34,
"code":"ARM",
"name":"Armenia"
},
"role":{
"code":"stop",
"name":"Escale"
}
},
{
"id":49,
"locality":{
"id":55,
"code":"hossegor",
"name":"Hossegor"
},
"role":{
"code":"drop_off",
"name":"Retour"
}
},
{
"id":50,
"locality":{
"id":55,
"code":"hossegor",
"name":"Hossegor"
},
"role":{
"code":"localisation",
"name":"Localisation"
}
}
]
}
]
''';

http.Response response = http.Response(jsonString, 200);
print(response);
responseJson = _response(response);
} on Exception {
//throw FetchDataException('No Internet connection');
}
return responseJson;
}

String _response(http.Response response) {
switch (response.statusCode) {
case 200:
print(response.body);
//var responseJson = jsonDecode(response.body);

//print(responseJson);
return response.body;
/* case 400:
throw BadRequestException(response.body.toString());
case 401:

case 403:
throw UnauthorisedException(response.body.toString());
case 500:

default:
throw FetchDataException(
'Error occured while Communication with Server with StatusCode : ${response.statusCode}');*/
}
}
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
List<ProductsResponse> productResponseList;

void _incrementCounter() async {
productResponseList = await fetchProducts();
print('${productResponseList[0].inventoryType}');
setState(() {
_counter++;
});
}

@override
void initState() {
// TODO: implement initState
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
productResponseList == null
? CircularProgressIndicator()
: Text('${productResponseList[0].inventoryType.name}'),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

关于flutter - 类型 'List<dynamic>'不是 'Map<String, dynamic>'类型的子类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60805129/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com