简体   繁体   English

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

[英]How to deal with backslashes in json strings php

There appears to be an oddity with json_encode and/or json_decode when attempting decode a string that was produced by json_encode:尝试解码由 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();

I've never experienced a problem previous to this, as I've never had to capture a string with backslashes in it until today.在此之前我从未遇到过问题,因为直到今天我才必须捕获带有反斜杠的字符串。 In reviewing the code above, I can encode/decode utilizing PHP's built in components.在查看上面的代码时,我可以使用 PHP 的内置组件进行编码/解码。 However if I attempt to decode a string that was produced by this encoder I get an error message.但是,如果我尝试解码此编码器生成的字符串,则会收到一条错误消息。 I've read in documentation items like " Predefined Constants " and other stack questions like " how remove the backslash (“\\”) in the json response using php? ".我读过文档项目,如“ 预定义常量”和其他堆栈问题,如“ 如何使用 php 删除 json 响应中的反斜杠(“\\”)? ”。 But I can't seem to find a reason WHY I can't decode a string that was produced by json_encode.但是我似乎找不到原因为什么我无法解码由 json_encode 生成的字符串。 The PHP version I'm using to test this code is 5.5.9.我用来测试此代码的 PHP 版本是 5.5.9。

I know I could be totally clueless by missing something, but should I be handling my string that was produced by json_encode differently if I attempt to use it elsewhere?我知道我可能会因为遗漏某些东西而完全一无所知,但是如果我尝试在其他地方使用它,我是否应该以不同的方式处理由 json_encode 生成的字符串?

The answer is in the question:答案在问题中:

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

You don't have to strip any slashes.您不必去除任何斜线。 On the contrary.相反。 You have to express the echo-ed text as PHP source code.您必须将回显文本表示为 PHP 源代码。

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

The backslash ( \\ ) is a special character in both PHP and JSON.反斜杠 ( \\ ) 是 PHP 和 JSON 中的特殊字符。 Both languages use it to escape special characters in strings and in order to represent a backslash correctly in strings you have to prepend another backslash to it, both in PHP and JSON.两种语言都使用它来转义字符串中的特殊字符,并且为了在字符串中正确表示反斜杠,您必须在 PHP 和 JSON 中添加另一个反斜杠。

Let's try to do the job of the PHP parser on the string above.让我们尝试在上面的字符串上完成 PHP 解析器的工作。 After the open parenthesis it encounters a string enclosed in single quotes .在左括号之后,它遇到一个用单引号括起来字符串 There are two special characters that needs escaping in single quote strings: the apostrophe ( ' ) and the backslash ( \\ ).有两个特殊字符需要在单引号字符串中转义:撇号 ( ' ) 和反斜杠 ( \\ )。 While the apostrophe always needs escaping, the PHP interpreter is forgiving and allows unescaped backslashes as long as they do not create confusion.虽然撇号总是需要转义,但 PHP 解释器是宽容的,并允许未转义的反斜杠,只要它们不会造成混淆。 However, the correct representation of the backslash inside single quoted strings is \\\\ .但是,单引号字符串中反斜杠的正确表示是\\\\

The string passed to function json_decode() is传递给函数json_decode()的字符串是

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

Please note that this is the exact list of characters processed on runtime and not a string represented in PHP or any other language.请注意,这是在运行时处理的准确字符列表,而不是用 PHP 或任何其他语言表示的字符串。 The languages have special rules for representing special characters.语言有表示特殊字符的特殊规则。 This is just plain text.这只是纯文本。

The text above is interpreted by function json_decode() that expects it to be a piece of JSON .上面的文本由函数json_decode()解释,它期望它是一段JSON JSON is a small language, it has special rules for encoding of special characters in strings. JSON是一种小语言,它对字符串中特殊字符的编码有特殊的规则。 The backslash is one of these characters and when it appears in a string it must be prepended by another backslash.反斜杠是这些字符之一,当它出现在字符串中时,必须在前面加上另一个反斜杠。 JSON is not forgiving; JSON不宽容; when it encounters a backslash it always treats it as an escape character for the next character in the string.当它遇到反斜杠时,它总是将其视为字符串中下一个字符的转义字符。

The object created by json_decode() after successful parsing of the JSON representation you pass them contains a single property named namespace whose value is: json_decode()在成功解析您传递给它们的 JSON 表示后创建的对象包含一个名为namespace的属性,其值为:

myCompany\package\subpackage

Note again that this is the actual string of characters and not a representation in any language.再次注意,这是实际的字符串,而不是任何语言的表示。

What went wrong?什么地方出了错?

Back to your code:回到你的代码:

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

The PHP parser interprets the code above using the PHP rules. PHP 解析器使用 PHP 规则解释上面的代码。 It understands that the json_decode() function must be invoked with the text {"namespace":"myCompany\\package\\subpackage"} as argument.它理解必须使用文本{"namespace":"myCompany\\package\\subpackage"}作为参数调用json_decode()函数。

json_decode() uses its rules and tries to interpret the text above as a piece of JSON representation. json_decode()使用其规则并尝试将上面的文本解释为一段 JSON 表示。 The quote ( " ) before myCompany tells it that "myCompany\\package\\subpackage" must be parsed as string. The backslash before package is interpreted as an escape character for p but \\p is not a valid escape sequence for strings in JSON. This is why it refuses to continue and returns NULL . myCompany之前的引号 ( " ) 告诉它必须将"myCompany\\package\\subpackage"解析为字符串。 package之前的反斜杠被解释为p的转义字符,但\\p不是 JSON 中字符串的有效转义序列。这这就是它拒绝继续并返回NULL

You will need to encode your double backslashes \\\\ into quadruple backslashes \\\\\\\\ because php interprets a backslash as an escape character in single and double quoted strings.您需要将双反斜杠\\\\编码为四重反斜杠\\\\\\\\因为 php 将反斜杠解释为单引号和双引号字符串中的转义字符。 This means that \\\\ is seen as \\ .这意味着\\\\被视为\\

This example illustrates what is happening这个例子说明了正在发生的事情

<?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;

This is the output这是输出

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

Please use the PHP native function stripslashes请使用PHP原生函数stripslashes

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

<?php
$str = 'myCompany\\package\\subpackage';
echo stripslashes(json_encode($str));
//output: myCompany\package\subpackage

Thats because PHP is converting the double slashes into a single slash before passing it to json_decode.那是因为 PHP 在将它传递给 json_decode 之前将双斜杠转换为单斜杠。 You will need to either escape the double slashes (a pain I know) or construct the object manually.您将需要逃避双斜线(我知道这是一种痛苦)或手动构造对象。

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

您可以只使用stripslashes函数来去除破折号,它会经过测试

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

Unfortunately, the json_decode() throws a JsonException when it is trying to decode a JSON string with double backslashes ("\\\\").不幸的是,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 />

To solve this problem, We could convert those double backslashes ("\\\\") into quad backslashes ("\\\\\\\\") using str_replace().为了解决这个问题,我们可以使用 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"
}

Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM