有没有更惯用的方法将 json 转换为 Crystal 中的特定哈希类型?
Is there a more idiomatic way to cast json to a specific Hash type in Crystal?
我有一个 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
returns a 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)
我有一个 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.parse
returns a 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)