下拉框选值后用Ajax拉取mysqli数据填充表单时JSON.parse解析失败
故障排查与解决步骤
一、PHP侧排查(解析失败90%的问题来源于此)
- 去除响应中多余输出
确保PHP文件<?php标签前无任何空格、换行、BOM头,文件末尾删除?>闭合标签,避免后续多余字符混入JSON输出。如果PHP执行过程中有报错、警告信息,会直接插入到响应内容中,破坏JSON格式,可在排查阶段临时在PHP开头添加代码开启错误显示:
直接访问接口地址error_reporting(E_ALL); ini_set('display_errors', 1);users.php?accountnum=2148查看返回内容,确认除了JSON数组外无其他多余内容。- 去除响应中多余输出
- 强制指定JSON响应头
在PHP输出JSON前添加响应头,明确返回内容格式,避免浏览器识别为普通文本:
header('Content-Type: application/json; charset=utf-8');- 强制指定JSON响应头
- 增加查询错误判断+修复SQL注入风险
原代码未处理SQL查询失败的场景,查询出错时会返回错误文本而非JSON,同时直接拼接SQL参数存在注入风险,修改后的PHP逻辑如下:
<?php // 原有数据库连接$conn逻辑请保留 $accountnum = $_GET['accountnum'] ?? ''; // 使用预处理语句避免注入,同时兼容特殊字符参数 $stmt = mysqli_prepare($conn, "SELECT * FROM accounts WHERE accountnum = ?"); mysqli_stmt_bind_param($stmt, 's', $accountnum); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); $accounts = mysqli_fetch_all($result, MYSQLI_ASSOC); // 强制指定JSON响应头 header('Content-Type: application/json; charset=utf-8'); echo json_encode($accounts); ?>- 增加查询错误判断+修复SQL注入风险
二、JS侧排查与修复
- 增加异常捕获定位解析错误
用try catch包裹JSON.parse逻辑,出错时打印原始响应内容,确认是否为合法JSON格式:
try { var accounts = JSON.parse(xhr.response); } catch (e) { console.error('JSON解析失败,原始响应内容:', xhr.response); console.error('错误信息:', e); return; }- 增加异常捕获定位解析错误
- 修复参数编码问题
GET请求的参数需要编码,避免特殊字符破坏URL结构,修改请求地址拼接逻辑:
xhr.open('GET', url+"?accountnum="+encodeURIComponent(eventResponse), true);- 修复参数编码问题
- 修复数组取值错误
接口返回的是包含对象的数组,不是直接返回对象,原代码直接accounts.id会返回undefined,不属于解析错误但会导致后续逻辑异常,正确取值方式为:
// 单条数据直接取数组第一个元素 if (accounts.length > 0) { const account = accounts[0]; console.log(account.id); console.log(account.name); // 渲染逻辑可以直接用account变量,不需要循环 }- 修复数组取值错误
- 可选优化:指定响应类型自动解析
可以在xhr.open后设置xhr.responseType = 'json',浏览器会自动将响应解析为JSON对象,不需要手动调用JSON.parse。
- 可选优化:指定响应类型自动解析
最终修复后的Ajax代码示例
function loadAccounts(eventResponse){ var xhr = new XMLHttpRequest(); var url = "users.php"; xhr.open('GET', url+"?accountnum="+encodeURIComponent(eventResponse), true); xhr.responseType = 'json'; // 自动解析JSON,无需手动parse xhr.onreadystatechange = function(){ if(xhr.readyState === XMLHttpRequest.DONE) { if(this.status == 200){ var accounts = xhr.response; var output = ''; // 因为是单条账号匹配,直接取第一个元素即可 if(accounts.length > 0) { const account = accounts[0]; output += '<div class="form-group">' + '<label for="accountname">AccountNum*</label>' + '<input type="text" class="form-control" id="accountnum" name="accountnum" value="'+account.accountnum+ '">' + '</div>'; } document.getElementById('accounts').innerHTML = output; } } } xhr.send() }
内容的提问来源于stack exchange,提问作者Grepler
相关产品推荐
相关产品推荐

