php怎么返回json数据给flutter_flutter接收php的json数据【教程】

2次阅读

php后端必须设置content-type为application/json并处理cors,flutter需显式jsondecode且校验键名;避免bom、隐藏输出及未等待异步

php怎么返回json数据给flutter_flutter接收php的json数据【教程】

PHP 后端必须设置正确的 Content-Type

Flutter 的 http.get()http.post() 默认会严格校验响应头,如果 PHP 没显式声明 Content-Type: application/json; charset=utf-8,即使返回的是合法 JSON,Dart 侧也可能解析失败或抛出 FormatException

常见错误现象:Flutter 控制台报 type 'String' is not a subtype of type 'map<string dynamic>'</string>,说明 Dart 没自动解析 JSON,而是把原始字符串当成了 String

  • 必须在输出 JSON 前调用 header('Content-Type: application/json; charset=utf-8');
  • 避免在 header() 前有任何输出(包括空格、BOM、echoprint),否则会触发 “Headers already sent” 错误
  • 推荐用 json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),防止中文转义和 URL 斜杠被编码

PHP 返回数组要确保键名是字符串且无特殊字符

Flutter 的 jsonDecode() 能解析标准 JSON,但 PHP 数组若含非法键名(如数字开头、空格、点号、中文键),json_encode() 仍能生成 JSON,但 Dart 解析后可能无法用 map['key'] 正常取值(尤其在 Map<string dynamic></string> 类型检查下)。

使用场景:比如你传 ['user_id' => 123, 'full name' => 'Alice'],Dart 里 map['full name'] 可用,但 ide 提示不安全;若用 ['1id' => 123],Dart 会拒绝类型推导为 Map<string dynamic></string>

立即学习PHP免费学习笔记(深入)”;

  • PHP 中统一用小写字母+下划线命名键名(如 user_idcreated_at
  • 避免直接 json_encode($_POST) —— 用户提交的键名不可控,应先映射到白名单字段
  • 对敏感字段(如密码)务必在 json_encode()unset() 或过滤

Flutter 端要用 jsonDecode() 显式解析,别依赖自动转换

Dart 的 http 包不会自动把响应体转成 Map,它只返回 Response 对象response.body 永远是 String。所谓“自动解析 JSON”是常见误解。

容易踩的坑:写成 final data = response.body; 就直接当 Map 用,结果运行时报错。

  • 必须导入 'dart:convert' 并调用 jsonDecode(response.body)
  • 建议包在 try-catch 里,捕获 FormatException(对应 PHP 返回了非 JSON 内容,比如 PHP 错误或 HTML)
  • 接口返回数组(如 [{"id":1},{"id":2}]),jsonDecode() 结果是 List<dynamic></dynamic>,需手动 .map((e) => MyModel.fromJson(e)).toList()

跨域问题(CORS)在调试时最常卡住请求

Flutter Web 或 android/ios 模拟器访问本地 PHP(如 http://10.0.2.2:8000/api.php)时,浏览器或 webview 会执行 CORS 检查。PHP 不返回正确响应头,请求直接被拦截,Flutter 甚至收不到响应(SocketException 或超时)。

不是所有环境都表现一致:Android 真机直连本机 PHP 通常无 CORS,但 Flutter Web 和 iOS 模拟器一定有。

  • PHP 文件开头加这三行:
    header('access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header('Access-Control-Allow-Headers: Content-Type');
  • 如果用了 POST 且带 Token,还需允许 Authorization 头:header('Access-Control-Allow-Headers: Content-Type, Authorization');
  • 生产环境禁止用 *,应指定 Flutter 前端域名(如 http://localhost:3000

实际开发中,最难排查的往往是 PHP 输出了隐藏字符(比如 UTF-8 BOM)导致 JSON 解析失败,或者 Flutter 没处理好异步等待就去读数据。这两处没日志、不报明确错误,但整个流程就卡住。

text=ZqhQzanResources