问题描述
我有一个JSON::Any
,当我访问“ params”键时,我得到了一个JSON::Any
表示以下内容:
{"a":0.9029593355545088,"b":2,"lh":1000,"ph":10,"pl":1}
我想将其转换为Hash(String,Float64)
,而我发现最简单的方法是使用to_json
,然后使用from_json
,因为Hash#from_json
不这样做。不能接受JSON::Any
类型。
params = Hash(String,Float64).from_json(json["params"].to_json)
似乎我在某个地方缺少概念或习语。有更好的方法吗?
PS
如果您想玩这个,下面是一个片段:
require "json"
json_string = %({"params": {"a": 1.2,"b": 2}})
json = JSON.parse(json_string)
Hash(String,Float64).from_json(json["params"].to_json)
请注意,在我的代码中,我无法轻松访问json_string
。因为它埋在了更大的json响应中,所以我必须对其进行解析才能解析到该位置,一旦解析,我就会得到一个JSON::Any
。因此,在使用from_json
将其转换为哈希之前,似乎需要将其转换为json字符串。
解决方法
JSON.parse
返回一个JSON::Any
,因此您可以使用其方便的投射帮助器:
json["params"].as_h.transform_values(&.raw.as(Float64|Int64).to_f)
但是,如果结构定义明确,最好使用JSON::Serializable
:
record ApiResponse,params : Hash(String,Float64) do
include JSON::Serializable
end
json_string = %({"params": {"a": 1.2,"b": 2}})
json = ApiResponse.from_json(json_string)
json.params # => {"a" => 1.2,"b" => 2.0}
甚至更好:
record ApiResponse,params : ApiParams do
include JSON::Serializable
end
record ApiParams,a : Float64,b : Float64 do
include JSON::Serializable
end
json_string = %({"params": {"a": 1.2,"b": 2}})
json = ApiResponse.from_json(json_string)
json.params # => ApiParams(@a=1.2,@b=2.0)