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

时间:2019-07-01 07:29:32

标签: ruby string-formatting backslash

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

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

结果是

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

在需要时(PHP的json_encode返回带有单个反斜杠的字符串)。

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

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

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

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

4 个答案:

答案 0 :(得分:2)

很抱歉,您的手边似乎确实有问题。关键是这样的:Why is the slash an escapable character in JSON?及其重复目标JSON: why are forward slashes escaped?。由于未转义的斜杠和转义的斜杠都允许,因此Ruby选择不转义,而PHP选择转义,这两种方法都是正确的。

(此外:谈论这个问题有点复杂,因为\是字符串文字和JSON字符串的转义字符。因此,在这个答案中,我要注意{{1 }}(或puts / echo)的所有值,以查看不包含字符串文字反斜杠的字符串转义,而仅看到字符串中实际存在的反斜杠。)

因此,JSON print_r是Ruby哈希{"url":"http:\/\/example.com\/test"}的表示形式,其中的斜杠被转义了(就像PHP的{ 'url' => 'http://example.com/test' }那样)。 Ruby的json_encode {“ url”:“ http://example.com/test”}`:

to_json' would render that as

另一方面,# 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"} (在Ruby和PHP中表示为字符串{"url":"http:\\/\\/example.com\\/test"})是Ruby哈希'{"url":"http:\\\\/\\\\/example.com\\\\/test"}'的表示,其中存在实际的反斜杠,但斜杠不逃脱。 PHP的{ 'url' => 'http:\/\/example.com\/test' }会将此值呈现为json_encode

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

PHP # 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

Ruby没有类似的选项来强制转义斜杠,但是由于斜杠在JSON中没有特殊含义,因此我们可以将# PHP echo json_encode('/'); # "\/" echo json_encode('/', JSON_UNESCAPED_SLASHES); # "/" 手动替换为/

\/

答案 1 :(得分:1)

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

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

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

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

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

答案 2 :(得分:0)

您的问题背后的问题可能是真正的问题。我不确定,因为您的问题对我来说还不是很清楚,所以我在这里用我的答案进行猜测/假设。

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

好吧,在这种情况下,您不必有任何问题(反斜线)。

让红宝石 .to_json JSON.generate(..))和 JSON.parse(..)解决红宝石部分并让 json_encode() json_decode()解决php部分,就完成了。

所以是红宝石:
-不要使用多余的转义反斜杠,让 .to_json 为您解决这个问题
-使用您将在浏览器中键入的文字网址字符串,如下所示:

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对象

答案 3 :(得分:0)

尝试如下

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

希望对您有帮助