Disons que j'ai ce Hash:
{
:info => [
{
:from => "Ryan Bates",
:message => "sup bra",
:time => "04:35 AM"
}
]
}
Je peux appeler le tableau d'informations en faisant hash[:info]
.
Maintenant, lorsque je transforme cela en JSON (JSON.generate), puis l'analyser (JSON.parse), j'obtiens ce hachage:
{
"info" => [
{
"from" => "Ryan Bates",
"message" => "sup bra",
"time" => "04:35 AM"
}
]
}
Maintenant, si j'utilise hash[:info]
il renvoie nil
, mais pas si j'utilise hash["info"]
.
Pourquoi est-ce? Et existe-t-il de toute façon pour corriger cette incompatibilité (outre l'utilisation des clés de chaîne dès le départ)?
Bref, non. Pensez-y de cette façon, le stockage de symboles dans JSON est le même que le stockage de chaînes dans JSON. Il est donc impossible de distinguer les deux lorsqu'il s'agit d'analyser la chaîne JSON. Vous pouvez bien sûr reconvertir les clés de chaîne en symboles, ou même créer une classe pour interagir avec JSON qui le fait automatiquement, mais je recommanderais simplement d'utiliser des chaînes.
Mais, juste pour le plaisir, voici les réponses à cette question les fois précédentes où elle a été posée:
ActiveSupport :: JSON décode les symboles de perte de hachage
Ou peut-être un HashWithIndifferentAccess
Le générateur JSON convertit les symboles en chaînes car JSON ne prend pas en charge les symboles. Étant donné que les clés JSON sont toutes des chaînes, l'analyse d'un document JSON produira un hachage Ruby avec des clés de chaîne par défaut.
Vous pouvez dire à l'analyseur d'utiliser des symboles au lieu de chaînes en utilisant le symbolize_names
option.
Exemple:
original_hash = {:info => [{:from => "Ryan Bates", :message => "sup bra", :time => "04:35 AM"}]}
serialized = JSON.generate(original_hash)
new_hash = JSON.parse(serialized, {:symbolize_names => true})
new_hash[:info]
#=> [{:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}]
Référence: http://www.Ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-parse
J'ai résolu mon problème similaire en appelant la méthode with_indifferent_access dessus
Ici, j'ai une chaîne json et nous pouvons l'assigner à la variable s
s = "{\"foo\":{\"bar\":\"cool\"}}"
Alors maintenant, je peux analyser les données avec la classe JSON et les affecter à h
h = JSON.parse(s).with_indifferent_access
Cela produira un hachage qui peut accepter une chaîne ou un symbole comme clé
h[:foo]["bar"]
#=> "cool"
Cela symbolisera récursivement toutes les clés du hachage.
(confirmé le Ruby 2.0)
Il est possible de modifier toutes les clés d'un hachage pour les convertir d'une chaîne en symbole:
symbol_hash = Hash[obj.map{ |k,v| [k.to_sym, v] }]
puts symbol_hash[:info]
# => {"from"=>"Ryan Bates", "message"=>"sup bra", "time"=>"04:35 AM"}
Malheureusement, cela ne fonctionne pas pour le hachage imbriqué dans le tableau. Vous pouvez cependant écrire une petite méthode récursive qui convertit toutes les clés de hachage:
def symbolize_keys(obj)
#puts obj.class # Useful for debugging
return obj.collect { |a| symbolize_keys(a) } if obj.is_a?(Array)
return obj unless obj.is_a?(Hash)
return Hash[obj.map{ |k,v| [k.to_sym, symbolize_keys(v)] }]
end
symbol_hash = symbolize_keys(hash)
puts symbol_hash[:info]
# => {:from=>"Ryan Bates", :message=>"sup bra", :time=>"04:35 AM"}
Vous ne pouvez pas utiliser cette option comme celle-ci
ActiveSupport::JSON.decode(str_json, symbolize_names: true)
Dans Rails 4.1 ou version ultérieure,
ActiveSupport::JSON.decode
n'accepte plus un hachage d'options pour MultiJSON. MultiJSON a atteint sa fin de vie et a été supprimé.
Vous pouvez utiliser symbolize_keys pour le gérer.
ActiveSupport::JSON.decode(str_json).symbolize_keys