Как сохранить одиночный обратный слеш в строке Ruby после форматирования to_json? - PullRequest
0 голосов
/ 01 июля 2019

Мне нужно закодировать некоторый хэш, содержащий строку 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: Проблема не в связи.Мне нужно кодировать мой JSON с помощью HMAC (SHA384).И результат отличается в PHP и Ruby, когда я использую строки URL.Если строка не содержит обратной косой черты, все работает нормально ...

Реализация PHP вводит обратную косую черту.Использование JSON в PHP выглядит так {"url":"http:\/\/example.com\/test"}, в то время как JSON в Ruby - {"url":"http:\\/\\/example.com\\/test"}

Ответы [ 4 ]

2 голосов
/ 01 июля 2019

Мои извинения, у вас, похоже, есть действительная проблема на вашей руке.Ключ в следующем: Почему косая черта - это экранируемый символ в JSON? и его дублируемая цель, JSON: почему экранированные косые черты экранированы? .Поскольку разрешены как неэкранированные, так и экранированные косые черты, Ruby решил не избегать их, а PHP решил избежать их, и оба подхода верны.

(За исключением: говорить об этом немного сложно, потому что\ является escape-символом как для строкового литерала, так и для строк JSON. Таким образом, в этом ответе я позабочусь о puts (или echo / print_r) всех значениях, чтобы увидеть строки, которыене имеют строкового литерала, экранирующего обратную косую черту, только те, которые фактически присутствуют в строках.)

Таким образом, JSON {"url":"http:\/\/example.com\/test"} является представлением хеша Ruby { 'url' => 'http://example.com/test' }, где экранированные косые черты (как PHP json_encode сделал бы это).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"}

С другой стороны, {"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('/', '\/')  # "\/"
1 голос
/ 01 июля 2019

Используйте одинарные кавычки вокруг строк, если вы не хотите иметь дело с экранированием от обратной косой черты.

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

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

Просто быстрое напоминание: в JSON необходимо экранировать обратную косую черту, поскольку они рассматриваются как управляющие символы.

Таким образом, когда PHP анализирует этот JSON-документ, вы получите строку с одним обратным слешем перед каждым слэшем.

0 голосов
/ 01 июля 2019

Попробуйте как показано ниже

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

Надеюсь, это поможет вам

0 голосов
/ 01 июля 2019

Проблема вашего вопроса, вероятно, является реальной проблемой. Я не уверен, потому что ваш вопрос мне не совсем понятен, поэтому я делаю предположение / предположение здесь с моим ответом.

Я предполагаю, что вы хотите общаться между ruby ​​и php, с json.

Ну, в этом случае у вас не должно быть проблем (с обратными слешами).

Пусть ruby ​​ .to_json ( JSON.generate (..) ) и JSON.parse (..) решают часть ruby ​​и позволяют json_encode () и json_decode () решите часть php, и все готово.

в рубине:
- не используйте лишние обратные слэши, пусть .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

...