Flutter集成Google Pay:paymentResult非有效JSON如何解析
问题解答
1. paymentResult的实际数据类型
- 它不是JSON字符串,是Flutter平台通道从Android/iOS原生层传递过来的原生结构化Map对象,对应Dart侧的类型是
Map<dynamic, dynamic>。 - 调用
toString()打印时看到键名没有双引号,是Dart中Map默认的toString()输出格式,不是标准JSON结构,直接用jsonDecode处理必然失败。 - 遍历看不到第三个条目的核心原因:
Map<String, dynamic>.from()仅做浅转换,外层key被转成了String,但嵌套的paymentMethodData等值仍然是Map<dynamic, dynamic>类型,遍历过程中触发隐式类型校验异常时会中断循环(部分Flutter版本下未捕获的这类异常不会直接打印红色报错,只会终止遍历逻辑),加上Flutter默认日志单条长度有1000字符左右的截断,容易误导判断条目不存在。
2. 正确解析提取字段的方式
不要用遍历键值对判断的方式取值,直接通过key索引访问即可,访问嵌套结构时手动做类型强转,解析逻辑外层包try-catch捕获潜在类型异常,示例代码:
void onGooglePayResult(paymentResult) { try { // 先强转外层为可安全访问的Map final resMap = Map<String, dynamic>.from(paymentResult); // 提取基础字段 final int apiVersion = resMap['apiVersion']; final int apiVersionMinor = resMap['apiVersionMinor']; // 提取paymentMethodData嵌套结构 final paymentMethodData = Map<String, dynamic>.from(resMap['paymentMethodData']); final String cardDesc = paymentMethodData['description']; final String payType = paymentMethodData['type']; // 提取卡信息、账单地址 final cardInfo = Map<String, dynamic>.from(paymentMethodData['info']); final billingAddress = Map<String, dynamic>.from(cardInfo['billingAddress']); final String userName = billingAddress['name']; final String phoneNumber = billingAddress['phoneNumber']; final String countryCode = billingAddress['countryCode']; final String address1 = billingAddress['address1']; final String postalCode = billingAddress['postalCode']; final String cardNetwork = cardInfo['cardNetwork']; final String cardDetail = cardInfo['cardDetails']; // 提取支付token(核心需要传给服务端的字段) final tokenData = Map<String, dynamic>.from(paymentMethodData['tokenizationData']); final String payToken = tokenData['token']; final String tokenType = tokenData['type']; // 后续把提取到的字段传给服务端即可 } catch (e) { log('Google Pay结果解析异常: $e'); } }
注意:所有嵌套Map取值后都要调用
Map<String, dynamic>.from()做一次转换,避免后续操作时出现dynamic类型的调用异常。
3. 快速转换为自定义实体类的方法
可以先写一个递归转换方法,把整个Map<dynamic, dynamic>完全转换成全String key的标准JSON结构Map,之后就可以和普通接口返回的JSON一样,配合常用的序列化方案(比如json_serializable、手写fromJson构造方法)转成自定义实体,递归转换工具方法示例:
Map<String, dynamic> convertDynamicMap(Map<dynamic, dynamic> originMap) { final result = <String, dynamic>{}; originMap.forEach((key, value) { if (value is Map<dynamic, dynamic>) { result[key.toString()] = convertDynamicMap(value); } else if (value is List) { result[key.toString()] = value.map((item) { if (item is Map<dynamic, dynamic>) return convertDynamicMap(item); return item; }).toList(); } else { result[key.toString()] = value; } }); return result; }
使用时只需要先调用一次转换方法,后续就可以走熟悉的JSON序列化逻辑:
void onGooglePayResult(paymentResult) { final standardJsonMap = convertDynamicMap(paymentResult); // 直接传入实体类fromJson方法即可 final gPayResult = MyPaymentResult.fromJson(standardJsonMap); }
对应的自定义实体类基础结构(可根据需要的字段删减):
class MyPaymentResult { int apiVersion; int apiVersionMinor; PaymentMethodData paymentMethodData; MyPaymentResult({this.apiVersion, this.apiVersionMinor, this.paymentMethodData}); MyPaymentResult.fromJson(Map<String, dynamic> json) { apiVersion = json['apiVersion']; apiVersionMinor = json['apiVersionMinor']; paymentMethodData = json['paymentMethodData'] != null ? PaymentMethodData.fromJson(json['paymentMethodData']) : null; } } // 其余PaymentMethodData、BillingAddress、TokenizationData等子类同理按照嵌套结构写fromJson即可
内容的提问来源于stack exchange,提问作者Boommeister
相关产品推荐
相关产品推荐

