2013-04-29 2 views
1

Мой контроллер получает строку JSON в Params, которая выглядит следующим образом:Руби/Rails - проблемы с JSON.parse/JSON.decode

{"serialized"=>"{\"key\":{\"subkey1\":"value",\"subkey2\":"value"}"}

В моем контроллере я стараюсь следующее:

JSON.parse(params[:serialized], symbolize_names: true) 

Который возвращает:

{:"key"=>{:subkey1=>"value", :subkey2=>"value"} 

Все вложенные подразделы символизировал; ключ был символизирован странным образом, поэтому он не отвечает на hash [key], но делает это для hash ["key"].

Если я иду через Rails стек:

ActiveSupport::JSON.decode(params[:serialized]).symbolize_keys 

я вернусь следующее:

{:"key"=>{"subkey1"=>"value", "subkey2"=>"value"} 

Почти так же, как и первый для вложенных ключей, за исключением; они не символизируются.

Я даже пробовал перебирать хэш, пытаясь символизировать ключи вручную; без успеха:

Hash[params[:serialized]{ |k, v| [k.to_sym, v] }] # returns {:"key"=>{"subkey1"=>"value", "subkey2"=>"value2"} 

Почему это происходит? Почему ключ обозначен как : «ключ» вместо : ключ?

UPD Удалены последняя строка (Как я мог исправить, так как мне нужен мой хэш, чтобы ответить на хэш [ключ] и не хэша [ «ключ»].), Так что вопрос выглядит менее прагматичен и более теоретический.

+0

FWIW ': ключ ==: "ключ" # => true' –

+0

Почему вы ожидаете' хэш [ключ] 'вместо' хэш [: ключ] 'быть возможно? – sawa

+0

@SeamusAbshere Да, я знаю, спасибо – Ruslan

ответ

0

Прежде всего, ключ и: «ключ» - это два способа выразить то же самое. На самом деле, если вы:

> :key == :"key" 
=> true 

так дали хэш такие как

h = {:"key" => "value"} 
h[:key] 
=> "value" 

Во-вторых, если у вас есть вложенные хэши, вы не только хотите, чтобы символизировать ключи вручную, вы также хотите символизируют ключи в значениях

Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }] 

конечно, вам нужно что-то более сложное, если у вас есть более чем на один уровень «nestesness»

+0

Ручное изменение ключей было именно в качестве примера. Я знаю это: ключ ==: «ключ». Я спросил, почему это происходит. то есть половина ключей преобразуется в: ключ, а другая половина преобразуется в: «ключ». symbolize_keys просто вызывает VARIABLE.to_sym, который оценивается в: ПЕРЕМЕННЫЙ. Так где же происходит магия? – Ruslan

+0

Понятно, я понял, что ваш вопрос более прагматичен, так как вы заканчиваете словами «Как я могу исправить это, так как мне нужен хэш для ответа на хэш [ключ], а не хэш [« ключ »]? Чтобы ответить на ваш вопрос, вы получите: «ключевую» нотацию, когда вы создаете символы, которые не могут быть представлены с использованием нотации: xxx. Например, ключ '' .to_sym' возвращает ': 'ключ' 'while' "key" .to_sym' возвращает ': key' – boulder

+0

Да, thats correct -« key \ »возвращает:« key », но заметьте место там ; В первом случае в пробе не было места: «key: – Ruslan

1

Я согласен с тем, что сказал @boulder выше. Но так как Hash[params[:serialized].symbolized_keys.map{ |k, v| [k.to_sym, v.symbolize_keys] }] символизирует до 1 уровня. Я никогда не пойду на это.

Это, вероятно, отличается от того, что вы просите, но доступ к ключ/значение хеш-функции в Rails, как правило, подходит как hash.key вместо hash[:key] или hash['key'].
Это основное соглашение, и это причина, по которой можно получить доступ к таким полям, как @user.name и т. Д.

Rails реализует это на OpenStruct. Для того, чтобы использовать его, вы можете сделать:

@foo = ActiveSupport::JSON.decode(params[:serialized]).symbolize_keys 
obj = OpenStruct.new(@foo) 
obj.key #=> {"subkey1"=>"value", "subkey2"=>"value"} 

Но опять же, OpenStruct создает объект до одного уровня для доступа с .key вместо «: ключ». Чтобы помочь этому, у нас есть Recursive OpenStruct, который отлично работает.

Так, лично я чувствую, что вы должны работать в Rails в сценарии, подобном этому (если придет).

Удачи :)

2

попробуйте рельсы консоли.

require 'json' 
string = {"serialized"=>"{\"key\":{\"subkey1\":"value",\"subkey2\":"value"}"} 
hash = JSON.parse string 
Смежные вопросы