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

时间:2015-08-17 18:08:00

标签: php json

尝试解码由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的内置组件进行编码/解码。但是,如果我尝试解码由此编码器生成的字符串,则会收到错误消息。我读过像“Predefined Constants”这样的文档项目以及其他堆栈问题,例如“how remove the backslash (“\”) in the json response using php?”。但我似乎无法找到一个原因为什么我无法解码由json_encode生成的字符串。我用来测试这段代码的PHP版本是5.5.9。

我知道错过一些东西我可能完全无能为力,但如果我试图在其他地方使用它,我是否应该处理由json_encode生成的字符串?

6 个答案:

答案 0 :(得分:5)

答案在于问题:

$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解析器的工作。在打开括号后,它会遇到string enclosed in single quotes。在单引号字符串中有两个需要转义的特殊字符:撇号(')和反斜杠(\)。虽然撇号总是需要转义,但PHP解释器是宽容的,只要它们不会产生混淆,就允许使用未转义的反斜杠。但是,单引号字符串中反斜杠的正确表示形式为\\

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

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

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

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

成功解析传递它们的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表示。 "之前的引用(myCompany)告诉它必须将"myCompany\package\subpackage"解析为字符串。 package之前的反斜杠被解释为p的转义字符,但\p不是JSON中字符串的有效转义序列。这就是为什么它拒绝继续并返回NULL

答案 1 :(得分:3)

您需要将双反斜杠\\编码为四重反斜杠\\\\,因为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

答案 2 :(得分:0)

这是因为PHP在将双斜杠转换为单斜杠之前将其传递给json_decode。你需要逃避双斜线(我知道的痛苦)或手动构造对象。

http://php.net/manual/en/language.types.string.php#language.types.string.syntax.single

答案 3 :(得分:0)

请使用PHP本机函数 <xsl:variable name="parameterValue" select="parameterValue" />

https://www.php.net/manual/en/function.stripslashes.php

stripslashes

答案 4 :(得分:-1)

您可以使用stripslashes功能删除短划线,它可以测试

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

答案 5 :(得分:-1)

不幸的是,json_decode() 在尝试解码带有双反斜杠 ("\\") 的 JSON 字符串时会抛出 JsonException。

<?php
var_dump(
    json_decode(
        '{"Server": "\\\\ComputerName\\MainDirectory\\SubDirectory"}',
    false, 512, JSON_THROW_ON_ERROR)
);

<br />
<b>Fatal error</b>:  Uncaught JsonException: Syntax error in [...][...]:2
Stack trace:
#0 [...][...](2): json_decode('{&quot;Server&quot;: &quot;\\\\C...', false, 512, 4194304)
#1 {main}
  thrown in <b>[...][...]</b> on line <b>2</b><br />

为了解决这个问题, 我们可以使用 str_replace() 将那些双反斜杠 ("\\") 转换为四反斜杠 ("\\\\")。

<?php
var_dump(
    json_decode(
        str_replace('\\','\\\\','{"Server": "\\\\ComputerName\\MainDirectory\\SubDirectory"}'),
        false, 512, JSON_THROW_ON_ERROR
    )
);


object(stdClass)#1 (1) {
    ["Server"]=>
    string(41) "\\ComputerName\MainDirectory\SubDirectory"
}

希望这会有所帮助。

相关问题