如何在PHP或PHP+JS中解析嵌套JSON及非标准JSON?
解析非标准/嵌套JSON的PHP及PHP+JavaScript方案
针对你遇到的这种嵌套JSON(双重编码)、还有不符合规范的非标准JSON(比如未加引号的标识符)解析问题,我整理了纯PHP和PHP+JS联合两种解决思路,具体如下:
一、纯PHP解决方案
1. 搞定双重编码的嵌套JSON
你提到的php_json_encode(JSON.stringify(...))这种场景,本质是JSON被双重编码了——JS先把对象转成JSON字符串,PHP又对这个字符串做了一次json_encode,导致最终内容是两层编码的结果。这种情况直接用json_decode两次就能解决:
// 先读取文件里的原始内容 $fileContent = file_get_contents('your-data-file.txt'); // 第一次解码:拿到JS层面stringify后的JSON字符串 $firstDecode = json_decode($fileContent, true); // 第二次解码:得到真正的嵌套对象结构 $finalData = json_decode($firstDecode['foo4'], true); // 假设foo4是那个双重编码的字段
如果整个文件内容都是双重编码的,更简单:
$rawContent = file_get_contents('your-data-file.txt'); $onceDecoded = json_decode($rawContent, true); $finalData = json_decode($onceDecoded, true);
2. 修复非标准JSON(比如未引号的标识符)
你的示例里"foo3":bar3.bar3_decimal明显不符合JSON规范——JSON要求字符串值必须加双引号,这里的bar3.bar3_decimal是裸标识符,直接用json_decode肯定报错。这种情况我们可以先做预处理,用正则把这类裸标识符转成合法的字符串:
$fileContent = file_get_contents('your-data-file.txt'); // 匹配类似 bar3.bar3_decimal 这种由字母、数字、下划线、点组成的裸标识符 $fixedContent = preg_replace('/(\s*:\s*)([a-zA-Z0-9_\.]+)(?=[,\}])/', '$1"$2"', $fileContent); // 现在尝试解码 $decodedData = json_decode($fixedContent, true); // 万一还有错误,打印错误信息排查 if (json_last_error() !== JSON_ERROR_NONE) { echo 'JSON解码失败:' . json_last_error_msg(); }
注意:这个正则是基础版,如果你的非标准JSON里有更复杂的裸标识符(比如带特殊字符),需要调整正则的匹配规则。
3. 混合场景(双重编码+非标准格式)
如果文件里同时存在两种问题,先修复非标准格式,再处理双重编码:
$raw = file_get_contents('your-data-file.txt'); // 第一步:修复裸标识符问题 $fixed = preg_replace('/(\s*:\s*)([a-zA-Z0-9_\.]+)(?=[,\}])/', '$1"$2"', $raw); // 第二步:处理双重编码 $onceDecoded = json_decode($fixed, true); $finalData = is_string($onceDecoded) ? json_decode($onceDecoded, true) : $onceDecoded;
二、PHP+JavaScript联合解决方案
如果纯PHP的正则预处理搞不定(比如非标准JSON格式太奇葩),可以借助JS的处理能力——毕竟原始数据是从JS那边来的,我们可以在JS里做更灵活的修复,再把结果传回PHP。
具体步骤:
- PHP读取文件内容,把它输出到前端页面的JS中
- JS尝试解析并修复非标准部分,处理双重编码
- JS把处理后的合法JSON发回PHP后端,供后续使用
示例代码:
前端展示页面(PHP渲染):
<?php $fileContent = file_get_contents('your-data-file.txt'); // 转义内容避免和JS的引号冲突 $escapedContent = htmlspecialchars($fileContent, ENT_QUOTES); ?> <!DOCTYPE html> <html> <body> <script> // 接收PHP传递的原始数据 const rawData = `<?= $escapedContent ?>`; let processedData; try { // 先尝试直接解析 processedData = JSON.parse(rawData); } catch (parseError) { // 解析失败,尝试修复裸标识符问题 const fixedData = rawData.replace(/(\s*:\s*)([a-zA-Z0-9_\.]+)(?=[,\}])/, '$1"$2"'); processedData = JSON.parse(fixedData); } // 处理双重编码的字段:如果某个字段是JSON字符串,再解析一次 if (processedData.foo4 && typeof processedData.foo4 === 'string') { processedData.foo4 = JSON.parse(processedData.foo4); } // 把处理好的数据发回后端 fetch('/save-processed-data.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(processedData), }) .then(res => res.json()) .then(result => { console.log('数据处理完成并保存:', result); }) .catch(err => { console.error('处理出错了:', err); }); </script> </body> </html>
后端接收接口(save-processed-data.php):
<?php // 接收JS传来的处理后数据 $processedData = json_decode(file_get_contents('php://input'), true); // 这里可以把数据保存到文件、数据库,或者做其他业务处理 file_put_contents('processed-result.json', json_encode($processedData, JSON_PRETTY_PRINT)); // 返回成功响应 echo json_encode(['status' => 'success', 'data' => $processedData]); ?>
三、实用调试技巧
- 在PHP里用
json_last_error()和json_last_error_msg()快速定位解码失败的原因,比如是语法错误还是其他问题 - 在JS里用
try-catch捕获解析错误,打印错误信息来调整修复规则 - 可以先把原始数据复制到JSON校验工具里,查看具体的语法错误,再针对性写修复逻辑
内容的提问来源于stack exchange,提问作者Pradeep Singh




