Dart中json解码后调用sort方法程序中断的原因及解决方法
问题触发原因
json.decode()的返回值是dynamic类型,编译期不会做类型校验:如果接口返回的JSON根结构不是数组(比如是单个对象、null、带业务包裹层的对象),运行时调用不存在的.sort()方法会直接抛出NoSuchMethodError,程序在该行中断。- 即使接口返回的是数组,如果数组内同时混杂多种类型值(比如字符串、数字、null、嵌套对象同时存在),
compareNatural方法做值对比时会触发类型不匹配异常,导致执行中断。 compareNatural本身仅支持字符串、数字这类基础可比较类型的自然排序,如果数组元素是嵌套对象,没有指定具体排序字段的前提下,方法无法完成对象对比,会直接报错。
解决方法
- 先加类型校验,不要直接对
dynamic类型的反序列化结果调用排序方法,参考实现:
response = await http.get(url); if(response.statusCode == 200) { var dataJson = response.body; var decodeResult = json.decode(dataJson); // 先校验根结构是否为数组 if (decodeResult is! List) { // 此处处理结构异常逻辑,比如打印错误日志、返回空结果 print('接口返回结构不符合预期,根节点非数组类型'); return; } // 显式转换为List类型,规避dynamic隐式错误 List matchData = decodeResult; // 过滤数组内无法参与自然排序的无效值 matchData = matchData.where((item) => item is String || item is num).toList(); // 执行排序 matchData.sort(compareNatural); }
- 针对性排查调整:
- 可以在sort调用外层加try-catch打印错误栈和运行时类型,快速定位根因:
try { matchData.sort(compareNatural); } catch (e) { print('排序执行异常:$e'); print('当前数据运行时类型:${matchData.runtimeType}'); } - 如果数组元素是对象,需要按对象内指定字段排序,不要直接传
compareNatural,自定义比较逻辑即可,比如按对象的title字段排序:matchData.sort((a, b) => compareNatural(a['title'], b['title'])); - 如果数组内的数字以字符串格式存储,提前做统一类型转换,避免对比时出现类型不匹配问题。
内容的提问来源于stack exchange,提问作者장인수
相关产品推荐
相关产品推荐

