我正在开发一个依靠API REST调用的flutter应用程序。来自API的响应有点复杂。当调用我的API(例如: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"
}
}
]
}
]
StackTrace:
I/flutter ( 2865): type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
[更新]:退货产品响应。fromJson(response)而不是response ProductsRespository:
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);
}
}
ProductsBloc:
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访问)
productView
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();
},
),
),
);
}
}
租户示例其他租户的相同逻辑(翻译、类型、子类型..)
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<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;
工作演示
完整代码
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),
),
);
}
}
我正在学习飞镖和颤振。现在,我尝试将JSON作为一种持久性方法。我犯了很多错误,都是关于类型和内容的。这是我遇到的最新错误:
在这里,我试图创建一个未来的listview生成器,得到一条错误消息:_TypeError(type'List'不是type'Map'的子类型)flift。我需要在列表视图中获取帖子中的所有数据。使用JSON到dart转换器quicktype创建模型类。木卫一 未来电话 模型
我在这里做了一个类似的帖子:问题,但我做了同样的事情,我一直是问题... 我有我的班级: ask API的方法: 当我询问我的API时,请求的结果是: {结果:[{id:2,题为:语言利用率是多少?难度:1,答案:[{id:9,题为:Oui,isCorrect:true},{id:10,题为:Non,isCorrect:false}],页码:3,下一步:http://localhost:3000/
我从Firestore示例中复制了一段代码: 但是我得到了这个错误 这里出了什么问题?
需要你的帮助解决这个错误在Flutter...也如何在其他屏幕上使用这个回调的实例? 这是我的留言。json数据模型 我的消息是一个模型。飞奔 这是我的留言。飞奔 _TypeError(类型“List”不是类型“Map”的子类型
我是一个新手,我尝试运行一个GitHub项目,但遇到了一个错误,比如类型ListDynamic不是类型ListInt的子类型。Github链接 误差线 以上代码文件 如有任何帮助,我们将不胜感激,并提前向您表示感谢。