PAYATHON 2026

如何将 PHP object array 转换为 JavaScript object array

排障赵师傅

结论

json_encode() 生成的 JSON 可以直接作为 JavaScript 表达式使用,因此直接赋值即可,无需放进双引号字符串后再调用 JSON.parse():

<script>
const portfolioData = <?= json_encode(
    $serviceDetails,
    JSON_HEX_TAG
    | JSON_HEX_AMP
    | JSON_HEX_APOS
    | JSON_HEX_QUOT
    | JSON_THROW_ON_ERROR
) ?>;
</script>

执行这段代码后,portfolioData 是一个 JavaScript 数组,数组中的每个元素都是对象。

为什么会出现语法错误

原代码如下:

<script>
let portfolioData = JSON.parse("<?php echo $convertData; ?>");
</script>

PHP 输出 JSON 后,浏览器接收到的代码大致是:

let portfolioData = JSON.parse("[{"services_idno":1,"services_name":"Front-End Web Development"}]");

外层 JavaScript 字符串使用了双引号:

JSON.parse("...")

JSON 内部也有大量双引号。浏览器读到 "services_idno" 前面的双引号时,会将它视为外层字符串的结束位置,导致整行代码无法通过 JavaScript 语法解析,并报出:

Uncaught SyntaxError: missing ) after argument list

错误发生在 JavaScript 解析阶段,此时 JSON.parse() 还没有运行。

把外层引号换成单引号仍然不可靠,因为数据库内容可能包含 '、换行、反斜杠或 </script> 等特殊内容。

推荐写法:直接输出 JSON

<?php

$serviceDetails = Services::services_find_all();

?>

<script>
const portfolioData = <?= json_encode(
    $serviceDetails,
    JSON_HEX_TAG
    | JSON_HEX_AMP
    | JSON_HEX_APOS
    | JSON_HEX_QUOT
    | JSON_THROW_ON_ERROR
) ?>;

console.log(portfolioData);
console.log(portfolioData[0].services_name);
</script>

生成的 JavaScript 大致如下:

const portfolioData = [
    {
        "services_idno": 1,
        "services_name": "Front-End Web Development",
        "services_desc": "We Can build a great looking website...",
        "services_image": "front.webp"
    }
];

JSON 本身是合法的 JavaScript 表达式,可以直接赋值,不需要 JSON.parse()。

JSON_HEX_* 选项用于处理可能影响内联 <script> 的字符。比如数据库内容中含有 </script> 时,未经处理的输出可能会让脚本元素提前结束。JSON_THROW_ON_ERROR 会在编码失败时抛出异常,避免程序静默得到 false 或无效输出。

如果确实需要使用 JSON.parse()

有些程序要求先把数据保存为字符串,再进行解析。这种情况下,应让 PHP 再执行一次字符串编码,而不是手工添加引号:

<?php

$serviceDetails = Services::services_find_all();

$json = json_encode(
    $serviceDetails,
    JSON_HEX_TAG
    | JSON_HEX_AMP
    | JSON_HEX_APOS
    | JSON_HEX_QUOT
    | JSON_THROW_ON_ERROR
);

?>

<script>
const portfolioData = JSON.parse(
    <?= json_encode(
        $json,
        JSON_HEX_TAG
        | JSON_HEX_AMP
        | JSON_HEX_APOS
        | JSON_HEX_QUOT
        | JSON_THROW_ON_ERROR
    ) ?>
);
</script>

第二次 json_encode() 会把 JSON 文本编码成合法的 JavaScript 字符串。当前场景不需要这层转换,直接赋值更简单。

也可以把 JSON 放在独立元素中

数据量较大,或者需要把数据与执行代码分开时,可以使用 application/json:

<script type="application/json" id="portfolio-data">
<?= json_encode(
    $serviceDetails,
    JSON_HEX_TAG
    | JSON_HEX_AMP
    | JSON_HEX_APOS
    | JSON_HEX_QUOT
    | JSON_THROW_ON_ERROR
) ?>
</script>

<script>
const jsonElement = document.getElementById('portfolio-data');
const portfolioData = JSON.parse(jsonElement.textContent);

console.log(portfolioData);
</script>

这种写法也建议保留 JSON_HEX_TAG,因为 HTML 解析器仍可能将数据中的 </script> 识别为元素的结束标签。

PHP 对象的属性要求

如果 $serviceDetails 中保存的是 PHP 对象,json_encode() 通常只能自动编码可访问的公共属性。例如:

class Service
{
    public int $services_idno;
    public string $services_name;
}

对于 private 或 protected 属性,可以先把对象转换为数组,也可以让类实现 JsonSerializable:

class Service implements JsonSerializable
{
    private int $services_idno;
    private string $services_name;

    public function jsonSerialize(): array
    {
        return [
            'services_idno' => $this->services_idno,
            'services_name' => $this->services_name,
        ];
    }
}

注意事项

  • 不要通过字符串拼接手工转义 JSON。
  • 不要用 htmlspecialchars() 代替 JSON 编码来处理内联脚本中的 JSON。<script> 内容采用不同的解析规则,HTML 实体可能不会按预期还原。
  • 数据库连接应使用正确的 UTF-8 字符集。无效的 UTF-8 数据会导致 json_encode() 失败,JSON_THROW_ON_ERROR 可以及时暴露这个问题。
  • \/、\u2014 等都是合法的 JSON 转义形式,解析后会分别还原为 / 和对应的 Unicode 字符。
  • 如果数据来自独立的 API 接口,接口应返回 Content-Type: application/json,前端通过 response.json() 读取,不需要把数据嵌入 HTML。

备注:内容仅供参考。