to_json 格式化后如何在 Ruby 字符串中保留单个反斜杠?

How to keep single backslash in Ruby string after to_json formating?

我需要对一些包含 URL 字符串的散列进行编码。我使用 to_json 方法,每个斜杠前需要反斜杠(因为 PHP 打印这样的字符串)。 例如:

hash = {"url":"http:\/\/example.com\/test"}
hash.to_json

结果是

{:url=>"http:\/\/example.com\/test"}

虽然我需要(和 PHP 的 json_encode returns 带有单个反斜杠的字符串)。

{:url=>"http:\/\/example.com\/test"}

在编码的情况下,保持 PHP 中的字符串非常重要。因为带有双反斜杠和单反斜杠的字符串会得到不同的结果。

更新: 问题不在于沟通。我需要使用 HMAC (SHA384) 对 JSON 进行编码。当我使用 URL 字符串时,PHP 和 Ruby 的结果不同。如果字符串不包含反斜杠,一切正常...

PHP 实现引入了反斜杠。 JSON 使用 PHP 看起来是 {"url":"http:\/\/example.com\/test"} 而 Ruby 的 JSON 是 {"url":"http:\/\/example.com\/test"}

如果您不想处理转义反斜杠,请在字符串周围使用单引号。

hash = { url: 'http:\/\/example.com\/test' }
json = hash.to_json
puts json

# => {"url":"http:\/\/example.com\/test"}

快速提醒:在 JSON 中,反斜杠需要转义,因为它们被视为控制字符。

这样,当 PHP 解析此 JSON 文档时,您将获得在每个斜杠之前带有一个反斜杠的字符串。

你的问题背后的问题可能是真正的问题。我不确定,因为你的问题对我来说不是很清楚,所以我在这里 guess/assumption 回答。

我这里的假设是你想在 ruby 和 php 之间进行通信,json。

好吧,在那种情况下你不必有问题(反斜杠)。

设ruby.to_json(JSON.generate(..))和JSON.parse(..) 求解 ruby 部分,让 json_encode()json_decode() 解决 php 部分,你就完成了。

所以在ruby中:
- 不要使用额外的 escaping-backslashes,让 .to_json 为您解决
- 使用您在浏览器中输入的文字 url 字符串,如下所示:

hash = {"url":"http://example.com/test"} # hash is a ruby object
puts hash.to_json                        # => {"url":"http://example.com/test"} is JSON (string)

然后在php:

var_dump( json_decode('{"url": "http://example.com/test"}') );

给你:

object(stdClass)#1 (1) {
  ["url"]=>
  string(23) "http://example.com/test"
}
var_dump( json_decode('{"url": "http:\/\/example.com\/test"}') );

给你:

object(stdClass)#1 (1) {
  ["url"]=>
  string(23) "http://example.com/test"
}

注意 JSON 两个字符串最终都在 PHP 中被正确解析并最终成为一个普通的 PHP 对象

像下面这样尝试

hash = {"url":"http:\/\/example.com\/test"}
hash[:url] = hash[:url].delete("\")
hash.to_json  #"{\"url\":\"http://example.com/test\"}"

希望对您有所帮助

抱歉,您手上的问题似乎确实存在。关键是:Why is the slash an escapable character in JSON? and its duplicate target, JSON: why are forward slashes escaped?。由于非转义斜线和转义斜线都允许,Ruby选择不转义,PHP选择转义,两种做法都是正确的。

(旁白:谈论这个有点复杂,因为 \ 是字符串文字和 JSON 字符串的转义字符。因此,在这个答案中,我注意 puts(或 echo/print_r)所有值,以查看没有字符串文字反斜杠转义的字符串,只有字符串中实际存在的反斜杠.)

因此,JSON {"url":"http:\/\/example.com\/test"} 是 Ruby 散列 { 'url' => 'http://example.com/test' } 的表示,其中斜线被转义(如 PHP 的 json_encode 会做)。 Ruby 的 to_json' would render that as{"url":"http://example.com/test"}`:

# Ruby
json1 = '{"url":"http:\/\/example.com\/test"}'
puts json1                        # => {"url":"http:\/\/example.com\/test"}
puts JSON.parse(json1)            # => {"url"=>"http://example.com/test"}
puts JSON.parse(json1).to_json    # => {"url":"http://example.com/test"}

# PHP
$json1 = '{"url":"http:\/\/example.com\/test"}';
echo $json1;                           # {"url":"http:\/\/example.com\/test"}
print_r(json_decode($json1));          # stdClass Object
                                       # (
                                       #     [url] => http://example.com/test
                                       # )
echo json_encode(json_decode($json1)); # {"url":"http:\/\/example.com\/test"}

另一方面,{"url":"http:\/\/example.com\/test"}(在Ruby和PHP中表示为字符串'{"url":"http:\\/\\/example.com\\/test"}')是Ruby散列{ 'url' => 'http:\/\/example.com\/test' },其中有实际的反斜杠,但斜杠没有转义。 PHP 的 json_encode 会将此值呈现为 {"url":"http:\\/\\/example.com\\/test"}.

# Ruby
json2 = '{"url":"http:\\/\\/example.com\\/test"}'
puts json2                        # => {"url":"http:\/\/example.com\/test"}
puts JSON.parse(json2)            # => {"url"=>"http:\/\/example.com\/test"}
puts JSON.parse(json2).to_json    # => {"url":"http:\/\/example.com\/test"}

# PHP
$json2 = '{"url":"http:\\/\\/example.com\\/test"}';
echo $json2;                           # {"url":"http:\/\/example.com\/test"}
print_r(json_decode($json2));          # stdClass Object
                                       # (
                                       #     [url] => http:\/\/example.com\/test
                                       # )
echo json_encode(json_decode($json2)); # {"url":"http:\\/\\/example.com\\/test"}

PHP json_encode 有一个选项可以防止 PHP 默认转义反斜杠:

# PHP
echo json_encode('/');                         # "\/"
echo json_encode('/', JSON_UNESCAPED_SLASHES); # "/"

Ruby 没有类似的强制转义斜线的选项,但是由于斜线在 JSON 中没有特殊含义,我们可以手动将 / 替换为 \/:

# Ruby
puts '/'.to_json                  # "/"
puts '/'.to_json.gsub('/', '\/')  # "\/"