
本文详解如何将多个结构为 ["data" => [obj]] 的 json 解析对象,合并为一个统一的 stdclass,其 data 属性为所有子对象扁平化后的单一数组。
在实际开发中(如批量调用 API 获取用户数据),我们常会收到多个相似结构的响应,例如每个用户返回一个形如 {"data": [{...}]} 的 JSON 字符串。经 json_decode() 后,得到的是一个对象数组,每个元素都带有一个嵌套的 data 数组(通常长度为 1)。但业务逻辑往往需要去重、聚合、统一分页或前端直连渲染——此时,必须将这些分散的 data 子项合并为一个扁平的、顶层为 stdClass 且 data 为纯对象数组的结构。
你当前的代码问题在于:
foreach ($data as $key => $single_data) {
$merged_data[$key] = $single_data->data; // ❌ 错误:保留了外层数组包装
}这导致 $merged_data[0] 是一个数组([0 => obj]),而非目标所需的直接对象。你需要提取每个 $single_data->data 的首项(即 $single_data->data[0]),再将其追加到一个新数组中,最后封装为 stdClass。
✅ 正确实现如下:
$data = [];
foreach ($this->get_authenticated_users() as $user) {
// ... 你的业务逻辑(如 API 请求、$json_data 获取等)...
$data[] = json_decode($json_data);
}
// 步骤 1:提取并扁平化所有 data[0] 对象
$flattened = [];
foreach ($data as $single_data) {
if (isset($single_data->data) && is_array($single_data->data) && !empty($single_data->data)) {
$flattened[] = $single_data->data[0]; // ✅ 关键:取第一个元素,跳过外层数组
}
}
// 步骤 2:构建最终目标结构:stdClass with 'data' => array of objects
$result = new stdClass();
$result->data = $flattened;
var_dump($result);输出即为你期望的结构:
object(stdClass)#1 (1) {
["data"]=>
array(2) {
[0]=>
object(stdClass)#2 (2) {
["timestamp"]=> string(24) "2022-02-23T01:26:50+0000"
["id"]=> string(17) "17899959194451041"
}
[1]=>
object(stdClass)#3 (2) {
["timestamp"]=> string(24) "2022-02-20T19:41:17+0000"
["id"]=> string(17) "17956063417578984"
}
}
}⚠️ 注意事项:
- 空值防护:务必检查 $single_data->data 是否存在、是否为非空数组,避免 Notice: Undefined index 或 Trying to access array offset on value of type null;
- 多元素 data 支持:若某次响应的 data 包含多个对象(如分页返回 10 条),应使用 array_merge($flattened, $single_data->data) 替代 [] 追加,确保全部合并;
- 类型一致性:所有 data 子项应为同构对象(字段名、类型一致),否则后续 JSON 序列化或 ORM 映射可能出错;
- 内存优化:若用户量极大,可考虑流式处理(不缓存全部 $data,边解码边合并),避免 OOM。
总结:核心思路是「解包 → 扁平收集 → 封装」。先穿透每层 data 数组拿到原始对象,再用简单循环聚合,最后用 new stdClass() 构建语义清晰的顶层容器。这一模式适用于 Facebook Graph API、Twitter v2、自定义微服务聚合等典型场景。










