If the response’s structure is well defined and known ahead of time, you could leverage JSON::Serializable - Crystal 1.4.1. Otherwise what you’re doing is fine, and is required for dynamic JSON data.
Another thing you could do is use the block version of HTTP::Client.get such that you don’t need to load the whole response body into memory, but can deserialize it in a streaming fashion. Ultimately this would look like:
require "http/client"
require "json"
data = HTTP::Client.get "https://api.caiyunapp.com/v2.5/96Ly7wgKGq6FhllM/116.391912,40.010711/weather.jsonp?hourlysteps=120&random=#{Random.rand}" do |resp|
JSON.parse(resp.body_io).as_h["result"].as_h
end
pp data
Your code was erroring since you’re using .as_a when the data is in fact a hash, so using as_h would return a hash of the data within the result object. From here if you wanted to access the hourly description you could do data["hourly"].as_h["description"].as_s.