My apologies, you do seem to have a valid issue on your hand. The key is this: Why is the slash an escapable character in JSON? and its duplicate target, JSON: why are forward slashes escaped?. Since both unescaped slashes and escaped slashes are allowed, Ruby chose to not escape them, and PHP chose to escape them, and both approaches are correct.
(Aside: there's a bit of a complication in talking about this because \ is an escape character both for a string literal, and for JSON strings. Thus, in this answer, I take care to puts (or echo/print_r) all the values, to see the strings that do not have the string literal backslash escapes, only the backslashes that are actually present in the strings.)
Thus, the JSON {"url":"http:\/\/example.com\/test"} is a representation of the Ruby hash { 'url' => 'http://example.com/test' }, where slashes are escaped (as PHP's json_encode would do it). Ruby's 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"}
On the other hand, {"url":"http:\\/\\/example.com\\/test"} (represented in Ruby and PHP as the string '{"url":"http:\\\\/\\\\/example.com\\\\/test"}') is a representation of the Ruby hash { 'url' => 'http:\/\/example.com\/test' }, where there are actual backslashes, but the slashes are not escaped. PHP's json_encode would render this value as {"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 has an option to prevent the PHP's default of escaping of backslashes:
# PHP
echo json_encode('/'); # "\/"
echo json_encode('/', JSON_UNESCAPED_SLASHES); # "/"
Ruby does not have a similar option to force escaping of slashes, but since a slash has no special meaning in JSON, we can just manually replace / with \/:
# Ruby
puts '/'.to_json # "/"
puts '/'.to_json.gsub('/', '\/') # "\/"
puts hashandp hash. But inside Ruby, as I think, it's anyway double backslash.hash.to_jsonis actually a Ruby literal and not JSON.{:url=>"http:\\/\\/example.com\\/test"}here is 2 backslashes before every slash, isn't it? I need a line where these 2 backslashes will be one backslash. Sorry for the misunderstanding, I asked as I see the problem.String#inspect, backslashes are used as escape characters in the display to escape special characters. In this case, the first backslash that is displayed tells you that the backslash after it is actually part of the string and not an escape character. So, there are two backslashes displayed so that you know that there is only one backslash actually in the string. You can trivially test this by checking the length of the string.