
本文讲解如何在 PHP 中处理从数据库读取的、结构为“JSON 数组 → 对象含 JSON 字符串字段 → 再次 JSON 解析”的多层嵌套响应,重点解决因未二次解码导致 NULL 或解析失败的问题。
本文讲解如何在 php 中处理从数据库读取的、结构为“json 数组 → 对象含 json 字符串字段 → 再次 json 解析”的多层嵌套响应,重点解决因未二次解码导致 `null` 或解析失败的问题。
在实际开发中,尤其在日志系统或遗留接口适配场景下,常会遇到数据库字段(如 RESPONSE)存储的是已序列化的 JSON 字符串,而非原生 JSON 对象。正如示例所示:数据库返回的是一个 JSON 数组,每个元素是一个对象,其 "RESPONSE" 键对应的值本身是经过 json_encode() 处理后的字符串(含转义双引号),例如:
{ "RESPONSE": "{\"Result\":[{\"ERRORS\":\"99012: Weborder number already exists : 20211049\"}]}" }此时若仅执行一次 json_decode($data),得到的 $decoded 中 RESPONSE 字段仍为字符串类型,直接访问 $decoded->RESPONSE->Result 会报错或返回 NULL——因为 PHP 无法对字符串调用对象属性。
✅ 正确做法是:两步解码(Double Decoding)
- 第一次 json_decode() 将原始数据库结果(JSON 字符串数组)转为 PHP 数组/对象;
- 遍历结果,对每个元素的 RESPONSE 字段再次调用 json_decode(),将其从字符串还原为可操作的数组或对象。
以下是推荐的健壮实现(Laravel 环境示例):
立即学习“PHP免费学习笔记(深入)”;
public function index(Request $request)
{
// 从数据库获取原始 JSON 字符串(假设 Log::get('RESPONSE') 返回完整 JSON 文本)
$rawJson = Log::get('RESPONSE');
// 第一步:解码外层 JSON(得到 PHP 数组)
$outerDecoded = json_decode($rawJson, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \RuntimeException('Failed to decode outer JSON: ' . json_last_error_msg());
}
// 第二步:遍历并逐个解码每个 RESPONSE 字段
$parsedResponses = [];
foreach ($outerDecoded as $item) {
if (!isset($item['RESPONSE']) || !is_string($item['RESPONSE'])) {
continue; // 跳过无效项
}
$innerDecoded = json_decode($item['RESPONSE'], true);
if (json_last_error() === JSON_ERROR_NONE) {
$parsedResponses[] = $innerDecoded;
} else {
// 可选:记录警告或保留原始字符串用于调试
\Log::warning('Failed to decode inner RESPONSE', ['raw' => $item['RESPONSE']]);
}
}
return response()->json($parsedResponses);
}? 关键注意事项:
- ✅ 始终检查 json_last_error(),避免静默失败;
- ✅ 使用 json_decode($json, true) 返回关联数组(更易处理),或省略 true 获取 stdClass 对象(需用 -> 访问);
- ⚠️ 不要混淆 json_encode() 与 json_decode():前者用于生成 JSON 字符串,后者用于解析;
- ? 若 RESPONSE 字段可能为空、null 或非字符串,务必添加类型校验(如 is_string()),防止 json_decode(null) 返回 null 引发后续逻辑错误;
- ? 调试技巧:使用 var_dump(gettype($item['RESPONSE']), $item['RESPONSE']) 快速确认字段真实类型。
总结:嵌套 JSON 解析的本质是「逐层剥茧」。当 var_dump() 显示某字段值被包裹在双引号内且含转义符(如 "{\"key\":...}"),即表明它仍是字符串,必须再次 json_decode()。掌握这一模式,可从容应对日志回溯、API 响应透传、配置字段存储等典型多层 JSON 场景。











