Flutter中jsonDecode返回String而非List的问题及两次解码生效原因
JSON解码两次才得到List的原因分析
问题背景
想要把目标JSON解码成List,但Flutter的jsonDecode方法第一次返回的是String类型而非List,直接转List会失败,连续调用两次jsonDecode(jsonDecode(response.body))却能成功得到List。
目标JSON数据
[{"TicketID":31,"EmpID":"11553","Name":"Test","Location":null,"PhoneExt":345345,"Code":null,"Reason":null,"Category":null,"Created":null,"Username":"abc","OtherLocation":null,"Room":null,"Floor":null,"CodeBlueDone":null,"CodeBlueDoneDate":null,"LocationCode":null,"PatientType":null,"EmergencyType":"Emergency","FilledDateTime":null,"SubmitDateTime":null,"Type":null,"CallTime":"2022-08-26T13:43:25.003","Status":"New"},{"TicketID":30,"EmpID":"12","Name":"dbdb","Location":null,"PhoneExt":123,"Code":null,"Reason":null,"Category":null,"Created":null,"Username":"abc","OtherLocation":null,"Room":null,"Floor":null,"CodeBlueDone":null,"CodeBlueDoneDate":null,"LocationCode":null,"PatientType":null,"EmergencyType":"Emergency","FilledDateTime":null,"SubmitDateTime":null,"Type":null,"CallTime":"2022-08-25T21:14:39.807","Status":"New"}]
解码相关代码
首次解码打印类型的代码:
if (response.statusCode == 200) { jsonDecode(response.body); print(jsonDecode(response.body).runtimeType); }
异步获取数据的代码:
Future<List> _getDataFromWeb() async { try { await http.post( Uri.parse(apiURL), headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, ).then((response) { if (response.statusCode == 200) { try { final resp = jsonDecode(response.body) as List?; print(resp.runtimeType); } catch (ex) { print("_getDataFromWeb() error: ${ex}"); } } else if (response.statusCode == 404) { print("Error 404: ${response.statusCode}"); } else { print("Error: ${response.statusCode}"); } }).catchError((error) { print("Error: " + error); }); } catch (ex) { print("API-ERR: $ex"); } }
原因分析
核心问题是接口返回的JSON数据被双重编码了:
- 第一次调用
jsonDecode(response.body)时,解码出来的是一个字符串——这个字符串本身就是你贴出来的那串JSON数组内容。 - 第二次调用
jsonDecode时,是把这个字符串形式的JSON再次解码,才得到了真正的List对象。
出现这种情况的本质是后端接口在返回数据时,先把数组序列化成JSON字符串,然后又把这个字符串再次做了一次JSON序列化,导致最终返回给前端的是一个被包裹的字符串类型JSON。比如正常应该返回[{"key":value},...],实际返回的却是"[{\"key\":value},...]"——外层多了引号,内部引号被转义,所以第一次解码只能拿到字符串,第二次解码才能解析成List。
验证与解决
- 验证方式:直接打印
response.body的原始内容,你会发现它是被引号包裹、内部字符转义的字符串,而非直接的JSON数组。 - 解决办法:
- 优先要求后端修复接口,确保只做一次JSON序列化,直接返回数组类型的JSON,这是最规范的解决方案。
- 如果后端暂时无法修改,前端可以先解码一次得到字符串,再解码第二次得到List,但这只是临时 workaround,不推荐长期使用。
内容的提问来源于stack exchange,提问作者Bassam
相关产品推荐
相关产品推荐

