本地网络下PHP服务器向Swift客户端返回JSON时出现解析错误
解决PHP返回JSON给Swift客户端的解析错误问题
这个错误NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.我之前也碰到过,本质是Swift的JSON解析器默认只认以数组[]或对象{}开头的标准JSON,但你的PHP输出大概率混入了额外内容,或者输出顺序不对导致JSON不规范。咱们一步步来修复:
先找PHP代码里的问题
- Content-Type头设置太晚:你原来的代码是在判断用户信息之后才设置
header('Content-Type: application/json');,但如果前面的require文件有输出,或者当Id/密码为空时直接输出JSON却没设置头,Swift可能会把返回内容当成普通文本,解析自然出错。 - 隐藏的额外输出:比如
Conn.php或MySQLDao.php文件开头/结尾可能有多余的空格、换行,甚至PHP的警告信息(比如数据库连接的warning),这些内容会插在JSON前面,让整个响应内容不再是标准的JSON结构。 - 输出逻辑不严谨:当
Id/密码为空时用return终止代码,但如果之前有任何输出(哪怕是个空格),都会破坏JSON的纯净性。
具体修复步骤
1. 把Content-Type头放在最最前面
一定要在任何输出(包括require文件)之前设置响应头,确保客户端从一开始就知道这是JSON数据:
<?php // 先关掉PHP的错误输出,避免警告混进JSON里 error_reporting(0); ini_set('display_errors', 0); // 提前设置JSON类型头 header('Content-Type: application/json'); // 再引入其他文件 require("Conn.php"); require("MySQLDao.php");
2. 检查引入的文件有没有多余输出
打开Conn.php和MySQLDao.php:
- 确保文件开头的
<?php前面没有任何空格、换行或字符; - 可以删掉文件末尾的
?>,这样能避免后面的换行被当成输出内容; - 检查这两个文件里有没有
echo、print之类的输出语句,全部删掉。
3. 统一输出逻辑,确保只输出合法JSON
调整你的代码,让所有分支都输出标准的JSON对象,并且用exit替代return来终止代码,避免后续执行带来的问题:
<?php error_reporting(0); ini_set('display_errors', 0); header('Content-Type: application/json'); require("Conn.php"); require("MySQLDao.php"); $returnValue = []; // 先判断参数是否存在,避免undefined index警告 $Id = isset($_POST["Id"]) ? htmlentities($_POST["Id"]) : ""; $password = isset($_POST["password"]) ? htmlentities($_POST["password"]) : ""; if(empty($Id) || empty($password)) { $returnValue["status"] = "error"; $returnValue["message"] = "Missing required field"; echo json_encode($returnValue); exit; // 直接终止,后面代码不执行 } $dao = new MySQLDao(); $dao->openConnection(); $userDetails = $dao->getUserDetailsWithPassword($Id, $password); if(!empty($userDetails)) { $returnValue["status"] = "Success"; $returnValue["message"] = "User is registered"; // 把用户详情放到data字段里,确保输出是一个完整的对象 $returnValue["data"] = $userDetails; } else { $returnValue["status"] = "error"; $returnValue["message"] = "User is not found"; } echo json_encode($returnValue); $dao->closeConnection(); exit;
4. 临时方案(不推荐,优先修复PHP)
如果暂时改不了PHP,也可以在Swift解析时允许解析片段,但这只是权宜之计,根源还是PHP输出不规范:
do { let json = try JSONSerialization.jsonObject(with: responseData, options: .allowFragments) // 处理解析后的JSON数据 } catch let error { print("解析错误:\(error.localizedDescription)") }
这些修改做完之后,你的PHP返回的就是纯净的标准JSON对象了,Swift那边自然就能正常解析啦~
内容的提问来源于stack exchange,提问作者Omar Salem
相关产品推荐
相关产品推荐

