如何解决错误 "type 'Null' is not a subtype of type 'String' in type cast"
How to solve error "type 'Null' is not a subtype of type 'String' in type cast"
我一直在尝试调试这个错误类型 'Null' is not a subtype of type 'String' in type cast 但找不到除了在触发 POST API 调用时生成错误之外,错误发生的确切位置。
店铺Class
import 'package:freezed_annotation/freezed_annotation.dart';
part 'shop.freezed.dart';
part 'shop.g.dart';
@freezed
class Shop with _$Shop {
factory Shop({
String? id,
@JsonKey(name: 'shopNumber')String? number,
@JsonKey(name: 'created') String? createdAt,
@JsonKey(name: 'updated') String? updatedAt,
int? calendar}) = _Shop;
factory Shop.fromJson(Map<String, dynamic> json) => _$ShopFromJson(json);
static Shop fromJsonModel(Map<String, dynamic> json) => Shop.fromJson(json);
}
Post 功能-创建店铺
Future<void> postShop() async {
Shop shop;
shop = await shopSvc.create(Shop(calendar: widget.calendar?.id, number: _shopNumber));
var newCalendar = widget.calendar?.copyWith(shop: shop);
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ShopInfoScreen(calendar: newCalendar!)));
}
} catch (e) {
print(e);
}
}
}
商店服务文件
class ShopService extends BaseHttpService {
final AppContext appContext;
late String _shopApi;
shopService(http.Client client, this.appContext) : super(httpClient: client) {
_shopApi = '${Globals.ApiEndpoint}/user/${appContext.currentCustomer.id}/shops/';
}
Future<Shop> create(Shop shop) async {
var token = await this.appContext.currentUser!.getIdToken();
final response = await callApi('$_cardApi/', token, method: 'post', payload: shop.toJson());
// return Shop.fromJsonModel(json.decode(response));
return shop;
}
}
基础 Http 服务文件
class BaseHttpService {
final Client httpClient;
BaseHttpService({required this.httpClient});
@protected
Future<String> callApi(String url, String token, {String method: 'get', Map<String, dynamic>? payload}) async {
late Response response;
Map<String, String> headers = {'Authorization': 'Bearer $token'};
if (method == 'get') response = await httpClient.get(Uri.parse(url), headers: headers);
else if (method == 'post') response = await httpClient.post(Uri.parse(url), headers: headers, body: payload);
else if (method == 'put') response = await httpClient.put(Uri.parse(url), headers: headers, body: payload);
else if (method == 'delete') response = await httpClient.delete(Uri.parse(url), headers: headers);
if (response.statusCode >= 300) {
print('statusCode : ' + response.statusCode.toString());
print(response.body.toString());
throw ClientException('Failed to load story with id $url');
}
return response.body;
}
}
基本上我想做的就是创建商店,它只需要正文中的 2 个字段,number
和 calendar
,其他字段将在数据库中默认设置。
代码在这一行的末尾失败 else if (method == 'post') response = await httpClient.post(Uri.parse(url), headers: headers, body: payload);
但我不知道问题出在哪里,因为我已经将 ?
放入变量中。
http包已经是最新版本 http: ^0.13.4
我已经在 POSTMAN 中尝试了下面的 POST 调用,它没有问题:
//Test 1
{
"id": null,
"shopNumber": "87678675",
"created": null,
"updated": null,
"calendar": 1
}
//Test 2
{
"shopNumber": "87678675",
"calendar": 1
}
堆栈跟踪:
#0 CastMap.forEach.<anonymous closure> (dart:_internal/cast.dart:288:25)
#1 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:400:8)
#2 CastMap.forEach (dart:_internal/cast.dart:287:13)
#3 mapToQuery (package:http/src/utils.dart:17:7)
#4 Request.bodyFields= (package:http/src/request.dart:137:12)
#5 BaseClient._sendUnstreamed (package:http/src/base_client.dart:87:17)
#6 BaseClient.post (package:http/src/base_client.dart:32:7)
#7 BaseHttpService.callApi (package:shop/services/base-http.dart:18:60)
#8 ShopService.create (package:shop/services/shop_service.dart:20:28)
<asynchronous suspension>
#9 _ShopAddScreenState.postShop (package:shop/shop_add_screen.dart:137:16)
<asynchronous suspension>
您的 api 调用可能 sending/getting Null
值,但它与您的类型 string
不匹配。或者字段名称不相同。
请检查 value
和字段名称。
更改下面 http-0.13.4/lib/src/utils.dart 中的代码片段对错误进行排序:"type 'Null'不是 type cast 中类型 'String' 的子类型。参考 github 我得到这段代码的问题 https://github.com/dart-lang/http/issues/75
这将从负载中删除所有空值,或者您可以在其中放置一些其他代码来管理空值。
来自:
String mapToQuery(Map<String, String> map, {Encoding encoding}) {
var pairs = <List<String>>[];
map.forEach((key, value) =>
pairs.add([Uri.encodeQueryComponent(key, encoding: encoding),
Uri.encodeQueryComponent(value, encoding: encoding)]));
return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
}
至:
String mapToQuery(Map<String, String> map, {Encoding encoding}) {
+ map.keys
+ .where((k) => (map[k] == null)).toList() // -- keys for null elements
+ .forEach(map.remove);
+
var pairs = <List<String>>[];
map.forEach((key, value) =>
pairs.add([Uri.encodeQueryComponent(key, encoding: encoding),
Uri.encodeQueryComponent(value, encoding: encoding)]));
return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
}
enter code here
在解决此 “type 'int' is not a subtype of type 'String' in type cast”后,我也遇到了另一个类似的错误。我相信这是由于 http-0.13.4/lib/src/utils.dart 中的这段代码,其中 http 客户端尝试将所有内容映射到上面引用的字符串。
String mapToQuery(Map<String, String> map, {Encoding encoding})
为了避免所有这些问题,我刚刚更改了函数:
来自:
Future<String> callApi(String url, String token, {String method: 'get', Map<String, dynamic>? payload})
至:
Future<String> callApi(String url, String token, {String method: 'get', String? payload})
然后我用 json.encode(shop)
代替了 shop.toJson()
Future<Shop> create(Shop shop) async {
var token = await this.appContext.currentUser!.getIdToken();
final response = await callApi('$_cardApi/', token, method: 'post', payload: json.encode(shop));
// return Shop.fromJsonModel(json.decode(response));
return shop;
}
通过将负载更改为 String
而不是 Map
,它会触发不同的输出,正如您在 http-0.13.4/[ 中的这段代码中看到的那样=78=].dart
if (headers != null) request.headers.addAll(headers);
if (encoding != null) request.encoding = encoding;
if (body != null) {
if (body is String) {
request.body = body;
} else if (body is List) {
request.bodyBytes = body.cast<int>();
} else if (body is Map) {
request.bodyFields = body.cast<String, String>();
} else {
throw ArgumentError('Invalid request body "$body".');
}
之前我触发 body is Map
将值转换为字符串:
else if (body is Map) {
request.bodyFields = body.cast<String, String>();
}
这是将我的 null
和 int
值转换为 String
,这导致了这两个错误。
现在我触发:
if (body is String) {
request.body = body;
}
希望这对以后遇到此问题的人有所帮助。
我一直在尝试调试这个错误类型 'Null' is not a subtype of type 'String' in type cast 但找不到除了在触发 POST API 调用时生成错误之外,错误发生的确切位置。
店铺Class
import 'package:freezed_annotation/freezed_annotation.dart';
part 'shop.freezed.dart';
part 'shop.g.dart';
@freezed
class Shop with _$Shop {
factory Shop({
String? id,
@JsonKey(name: 'shopNumber')String? number,
@JsonKey(name: 'created') String? createdAt,
@JsonKey(name: 'updated') String? updatedAt,
int? calendar}) = _Shop;
factory Shop.fromJson(Map<String, dynamic> json) => _$ShopFromJson(json);
static Shop fromJsonModel(Map<String, dynamic> json) => Shop.fromJson(json);
}
Post 功能-创建店铺
Future<void> postShop() async {
Shop shop;
shop = await shopSvc.create(Shop(calendar: widget.calendar?.id, number: _shopNumber));
var newCalendar = widget.calendar?.copyWith(shop: shop);
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ShopInfoScreen(calendar: newCalendar!)));
}
} catch (e) {
print(e);
}
}
}
商店服务文件
class ShopService extends BaseHttpService {
final AppContext appContext;
late String _shopApi;
shopService(http.Client client, this.appContext) : super(httpClient: client) {
_shopApi = '${Globals.ApiEndpoint}/user/${appContext.currentCustomer.id}/shops/';
}
Future<Shop> create(Shop shop) async {
var token = await this.appContext.currentUser!.getIdToken();
final response = await callApi('$_cardApi/', token, method: 'post', payload: shop.toJson());
// return Shop.fromJsonModel(json.decode(response));
return shop;
}
}
基础 Http 服务文件
class BaseHttpService {
final Client httpClient;
BaseHttpService({required this.httpClient});
@protected
Future<String> callApi(String url, String token, {String method: 'get', Map<String, dynamic>? payload}) async {
late Response response;
Map<String, String> headers = {'Authorization': 'Bearer $token'};
if (method == 'get') response = await httpClient.get(Uri.parse(url), headers: headers);
else if (method == 'post') response = await httpClient.post(Uri.parse(url), headers: headers, body: payload);
else if (method == 'put') response = await httpClient.put(Uri.parse(url), headers: headers, body: payload);
else if (method == 'delete') response = await httpClient.delete(Uri.parse(url), headers: headers);
if (response.statusCode >= 300) {
print('statusCode : ' + response.statusCode.toString());
print(response.body.toString());
throw ClientException('Failed to load story with id $url');
}
return response.body;
}
}
基本上我想做的就是创建商店,它只需要正文中的 2 个字段,number
和 calendar
,其他字段将在数据库中默认设置。
代码在这一行的末尾失败 else if (method == 'post') response = await httpClient.post(Uri.parse(url), headers: headers, body: payload);
但我不知道问题出在哪里,因为我已经将 ?
放入变量中。
http包已经是最新版本 http: ^0.13.4
我已经在 POSTMAN 中尝试了下面的 POST 调用,它没有问题:
//Test 1
{
"id": null,
"shopNumber": "87678675",
"created": null,
"updated": null,
"calendar": 1
}
//Test 2
{
"shopNumber": "87678675",
"calendar": 1
}
堆栈跟踪:
#0 CastMap.forEach.<anonymous closure> (dart:_internal/cast.dart:288:25)
#1 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:400:8)
#2 CastMap.forEach (dart:_internal/cast.dart:287:13)
#3 mapToQuery (package:http/src/utils.dart:17:7)
#4 Request.bodyFields= (package:http/src/request.dart:137:12)
#5 BaseClient._sendUnstreamed (package:http/src/base_client.dart:87:17)
#6 BaseClient.post (package:http/src/base_client.dart:32:7)
#7 BaseHttpService.callApi (package:shop/services/base-http.dart:18:60)
#8 ShopService.create (package:shop/services/shop_service.dart:20:28)
<asynchronous suspension>
#9 _ShopAddScreenState.postShop (package:shop/shop_add_screen.dart:137:16)
<asynchronous suspension>
您的 api 调用可能 sending/getting Null
值,但它与您的类型 string
不匹配。或者字段名称不相同。
请检查 value
和字段名称。
更改下面 http-0.13.4/lib/src/utils.dart 中的代码片段对错误进行排序:"type 'Null'不是 type cast 中类型 'String' 的子类型。参考 github 我得到这段代码的问题 https://github.com/dart-lang/http/issues/75
这将从负载中删除所有空值,或者您可以在其中放置一些其他代码来管理空值。
来自:
String mapToQuery(Map<String, String> map, {Encoding encoding}) {
var pairs = <List<String>>[];
map.forEach((key, value) =>
pairs.add([Uri.encodeQueryComponent(key, encoding: encoding),
Uri.encodeQueryComponent(value, encoding: encoding)]));
return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
}
至:
String mapToQuery(Map<String, String> map, {Encoding encoding}) {
+ map.keys
+ .where((k) => (map[k] == null)).toList() // -- keys for null elements
+ .forEach(map.remove);
+
var pairs = <List<String>>[];
map.forEach((key, value) =>
pairs.add([Uri.encodeQueryComponent(key, encoding: encoding),
Uri.encodeQueryComponent(value, encoding: encoding)]));
return pairs.map((pair) => "${pair[0]}=${pair[1]}").join("&");
}
enter code here
在解决此 “type 'int' is not a subtype of type 'String' in type cast”后,我也遇到了另一个类似的错误。我相信这是由于 http-0.13.4/lib/src/utils.dart 中的这段代码,其中 http 客户端尝试将所有内容映射到上面引用的字符串。
String mapToQuery(Map<String, String> map, {Encoding encoding})
为了避免所有这些问题,我刚刚更改了函数:
来自:
Future<String> callApi(String url, String token, {String method: 'get', Map<String, dynamic>? payload})
至:
Future<String> callApi(String url, String token, {String method: 'get', String? payload})
然后我用 json.encode(shop)
shop.toJson()
Future<Shop> create(Shop shop) async {
var token = await this.appContext.currentUser!.getIdToken();
final response = await callApi('$_cardApi/', token, method: 'post', payload: json.encode(shop));
// return Shop.fromJsonModel(json.decode(response));
return shop;
}
通过将负载更改为 String
而不是 Map
,它会触发不同的输出,正如您在 http-0.13.4/[ 中的这段代码中看到的那样=78=].dart
if (headers != null) request.headers.addAll(headers);
if (encoding != null) request.encoding = encoding;
if (body != null) {
if (body is String) {
request.body = body;
} else if (body is List) {
request.bodyBytes = body.cast<int>();
} else if (body is Map) {
request.bodyFields = body.cast<String, String>();
} else {
throw ArgumentError('Invalid request body "$body".');
}
之前我触发 body is Map
将值转换为字符串:
else if (body is Map) {
request.bodyFields = body.cast<String, String>();
}
这是将我的 null
和 int
值转换为 String
,这导致了这两个错误。
现在我触发:
if (body is String) {
request.body = body;
}
希望这对以后遇到此问题的人有所帮助。