
本文详解如何在 php 中将带字符串键(如 "1", "2", "3")的关联数组转换为连续数字索引的纯数组,从而生成符合预期结构的 json 输出。
本文详解如何在 php 中将带字符串键(如 "1", "2", "3")的关联数组转换为连续数字索引的纯数组,从而生成符合预期结构的 json 输出。
在使用 MySQLi 查询多对一关系(例如一道题目对应多个答案)时,常通过 QuestionId 作为临时键来聚合数据,例如:
$questions[$r['QuestionId']] = [ /* ... */ ];
这种方式虽便于去重和追加子项(如 answers),但最终 $questions 是一个关联数组(key 为 '1', '2', '3' 等字符串),而非期望的索引数组(key 为 0, 1, 2)。当执行 array_push($quest_arr['data'], $questions) 后,整个 $questions 被作为单个元素压入 data 数组,导致 JSON 中出现嵌套对象并保留原始字符串键 —— 这正是问题中 data: [{ "1": {...}, "2": {...} }] 的根源。
✅ 正确做法是:不使用 array_push 包裹整个 $questions,而是直接将其转换为索引数组,并赋值给 $quest_arr['data']。
只需两行关键修改:
// 替换原来的这两行: // array_push($quest_arr['data'], $questions); // 改为: $questions = array_values($questions); // 丢弃原键,重置为 0-based 数字索引 $quest_arr['data'] = $questions; // 直接赋值,而非 push 到新数组
array_values() 是核心函数:它提取数组所有值,并重新按整数索引(0, 1, 2...)排序,彻底移除原始字符串键。配合直接赋值,即可得到扁平、有序的 JSON 数组结构。
完整修正后的逻辑片段如下:
if ($num > 0) {
$quest_arr = [
'error' => 'false',
'message' => 'Success',
'data' => []
];
$questions = [];
foreach ($result as $r) {
$qid = (int)$r['QuestionId']; // 强制转为整型,避免潜在类型混淆
if (!isset($questions[$qid])) {
$questions[$qid] = [
'QuestionId' => $qid,
'question' => $r['QuestionName'],
'answers' => []
];
}
$answers = $r['AnswerID'] === null ? null : (int)$r['AnswerID'];
$questions[$qid]['answers'][] = $answers;
}
// ✅ 关键修复:转为索引数组并直接赋值
$quest_arr['data'] = array_values($questions);
echo json_encode($quest_arr, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE);
} else {
echo json_encode([
'error' => 'true',
'message' => 'Error'
]);
}
⚠️ 注意事项:
- 避免使用
array_push($arr, $assoc)将整个关联数组当作一个元素推入;应确保$arr接收的是“展开后”的索引结构。 - 若后续需保持
QuestionId可查,可在前端或数据库层额外提供唯一标识字段,而非依赖 PHP 数组键。 -
JSON_NUMERIC_CHECK对整型安全,但建议对AnswerID等字段显式类型转换(如(int)或filter_var(..., FILTER_VALIDATE_INT)),防止null或字符串污染数值字段。
通过 array_values(),你无需重构查询或引入额外库,即可优雅解决动态键问题,输出干净、标准、易解析的 JSON 数组。











