如何处理 json 字符串中的反斜杠 php

2022-08-30 22:23:52

在尝试解码由json_encode生成的字符串时,json_encode和/或json_decode似乎有一个奇怪的现象:

    $object = new stdClass;
    $object->namespace = 'myCompany\package\subpackage';

    $jsonEncodedString = json_encode($object);
    echo $jsonEncodedString;
    // Result of echo being:
    // {"namespace":"myCompany\\package\\subpackage"}

    $anotherObject = json_decode($jsonEncodedString);
    echo $anotherObject->namespace;
    // Result of echo being:
    // myCompany\package\subpackage


    $yetAnotherObject = json_decode('{"namespace":"myCompany\\package\\subpackage"}');
    // Result should be:
    // myCompany\package\subpackage
    // But returns an invalid string sequence error instead...
    echo json_last_error_msg();

在此之前,我从未遇到过问题,因为直到今天,我才必须捕获带有反斜杠的字符串。在查看上面的代码时,我可以利用PHP的内置组件进行编码/解码。但是,如果我尝试解码此编码器生成的字符串,则会收到一条错误消息。我已经在文档项目中阅读了“预定义常量”和其他堆栈问题,例如“如何使用php删除json响应中的反斜杠(”\“)。)。但我似乎找不到为什么我无法解码由json_encode产生的字符串的原因。我用来测试此代码的PHP版本是5.5.9。

我知道我可能会因为错过一些东西而完全无能为力,但是如果我尝试在其他地方使用它,我是否应该以不同的方式处理json_encode产生的字符串?


答案 1

答案就在问题中:

$jsonEncodedString = json_encode($object);
echo $jsonEncodedString;
// Result of echo being:
// {"namespace":"myCompany\\package\\subpackage"}

您不必去除任何斜杠。恰恰相反。您必须将回显文本表示为PHP源代码。

$yetAnotherObject = json_decode('{"namespace":"myCompany\\\\package\\\\subpackage"}');

反斜杠 () 是 PHP 和 JSON 中的特殊字符。这两种语言都使用它来转义字符串中的特殊字符,为了在字符串中正确表示反斜杠,您必须在PHP和JSON中为其预置另一个反斜杠。\

让我们尝试在上面的字符串上完成PHP解析器的工作。在左括号之后,它会遇到一个用单引号括起来的字符串。有两个特殊字符需要在单引号字符串中转义:撇号 () 和反斜杠 ()。虽然撇号总是需要转义,但PHP解释器是宽容的,并且允许未转义的反斜杠,只要它们不会造成混淆。但是,单引号字符串内反斜杠的正确表示形式是 。'\\\

传递给函数的字符串为json_decode()

{"namespace":"myCompany\\package\\subpackage"}

请注意,这是在运行时处理的字符的确切列表,而不是用 PHP 或任何其他语言表示的字符串。这些语言具有表示特殊字符的特殊规则。这只是纯文本。

上面的文本由函数解释,该函数期望它是 的一部分。 是一种小语言,它对字符串中的特殊字符的编码有特殊的规则。反斜杠是这些字符之一,当它出现在字符串中时,它必须由另一个反斜杠前置。 不宽容;当它遇到反斜杠时,它始终将其视为字符串中下一个字符的转义字符。json_decode()JSONJSONJSON

成功解析您传递给它们的 JSON 表示形式后创建的对象包含一个名为以下属性的属性:json_decode()namespace

myCompany\package\subpackage

再次注意,这是实际的字符串,而不是任何语言的表示形式。

哪里出错了?

回到你的代码:

$yetAnotherObject = json_decode('{"namespace":"myCompany\\package\\subpackage"}');

PHP 解析器使用 PHP 规则解释上述代码。它理解必须使用文本作为参数来调用函数。json_decode(){"namespace":"myCompany\package\subpackage"}

json_decode()使用其规则并尝试将上述文本解释为一段 JSON 表示形式。前面的引号 () 告诉它必须解析为字符串。前面的反斜杠被解释为 JSON 中字符串的转义字符,但不是有效的转义序列。这就是为什么它拒绝继续并返回的原因 。"myCompany"myCompany\package\subpackage"packagep\pNULL


答案 2

您需要将双反斜杠编码为四重反斜杠,因为 php 将反斜杠解释为单引号和双引号字符串中的转义字符。这意味着它被视为 。\\\\\\\\\

此示例说明了正在发生的事情

<?php
$str = '{"namespace":"myCompany\\package\\subpackage"}';
echo $str, PHP_EOL; // \\ seen as \
$yetAnotherObject = json_decode($str);
echo json_last_error_msg(), PHP_EOL;

var_dump(json_decode(str_replace('\\', '\\\\', $str)));
echo json_last_error_msg(), PHP_EOL;

这是输出

$ php test.php
{"namespace":"myCompany\package\subpackage"}
Syntax error
class stdClass#1 (1) {
  public $namespace =>
  string(28) "myCompany\\package\\subpackage"
}
No error

推荐