Dart中BigInt转JSON报无toJson实例方法错误如何解决
Dart BigInt序列化JSON报toJson方法不存在的修复方法
问题环境
- Dart SDK版本:2.17.3 (stable)(发布时间2022-06-01 11:06:41 +0200)
- 运行平台:macos_arm64
问题复现代码
业务场景为调用接口更新待办事项属性,实现代码如下:
static Future<bool> updateTodoProperties(Todo todo) async { Map<String,Object> params = new HashMap(); params.putIfAbsent("id", () => todo.id); params.putIfAbsent("name", () => todo.name); var response = await RestClient.patch("/tik/todo/v1/update",params); if (RestClient.respSuccess(response)) { return true; }else{ return false; } }
运行时抛出如下错误:
NoSuchMethodError: Class '_BigIntImpl' has no instance method 'toJson'. Receiver: Instance of '_BigIntImpl' Tried calling: toJson
报错原因
Dart标准库中的JSON序列化逻辑默认仅支持num、String、bool、null、List、Map几类基础类型,遇到未内置支持的类型时,会自动尝试调用实例的toJson()方法完成转换。而BigInt类型的内部实现_BigIntImpl没有自带toJson方法,因此序列化时直接抛出NoSuchMethodError。
修复方案
根据项目实际场景选以下任意一种方案即可:
方案1:单字段手动转换(改造成本最低,适合少量BigInt字段场景)
绝大多数后端接口为了避免前端JS大整数精度丢失,会要求超大整数ID以字符串格式传递,组装参数时手动把BigInt转成对应类型即可:
static Future<bool> updateTodoProperties(Todo todo) async { Map<String,Object> params = new HashMap(); // 手动将BigInt类型的id转为字符串,若后端要求传数字可改为 todo.id.toInt() params.putIfAbsent("id", () => todo.id.toString()); params.putIfAbsent("name", () => todo.name); var response = await RestClient.patch("/tik/todo/v1/update",params); return RestClient.respSuccess(response); }
方案2:配置自定义JSON序列化规则(适合项目中多处使用BigInt的场景)
如果项目里大量接口需要传递BigInt类型字段,可以给JSON编码器配置自定义转换逻辑,避免每个字段重复手动转换。如果使用的RestClient支持自定义序列化器,参考如下配置:
// 自定义支持BigInt的JSON编码器 final jsonEncoder = JsonEncoder((dynamic obj) { if (obj is BigInt) { // 按接口要求返回字符串或数字 return obj.toString(); } return obj; }); // 后续序列化请求参数时统一使用该编码器处理即可
方案3:扩展BigInt方法(全局生效,一劳永逸)
通过Dart的扩展方法特性,给BigInt类型全局添加toJson实现,配置一次后原有业务代码不需要做任何修改即可正常序列化:
extension BigIntJsonSupport on BigInt { // 按接口要求调整返回值类型,传字符串用toString,传数字用toInt String toJson() => this.toString(); }
注意:如果涉及接口返回值反序列化到BigInt的逻辑,需要同步处理类型转换:字符串值用
BigInt.parse(源值)转换,数字值用BigInt.from(源值)转换即可。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

