You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在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。

具体步骤:

  1. PHP读取文件内容,把它输出到前端页面的JS中
  2. JS尝试解析并修复非标准部分,处理双重编码
  3. 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

火山引擎 最新活动