Reputation: 681
So I have a JSON file of a somewhat known format { String => JSON::Type, ... }
. So it is basically of type Hash(String, JSON::Type)
. But when I try and read it from file to memory like so: JSON.parse(File.read(@cache_file)).as(Hash(String, JSON::Type))
I always get an exception: can't cast JSON::Any to Hash(String, JSON::Type)
I'm not sure how I am supposed to handle the data if I can't cast it.
What I basically want to do is the following:
And of course read from / write to file...
Here's the whole thing I've got so far:
class Cache
def initialize(@cache_file = "/tmp/cache_file.tmp")
end
def cache(cache_key : (String | Symbol))
mutable_cache_data = data
value = mutable_cache_data[cache_key.to_s] ||= yield.as(JSON::Type)
File.write @cache_file, mutable_cache_data
value
end
def clear
File.delete @cache_file
end
def data
unless File.exists? @cache_file
File.write @cache_file, {} of String => JSON::Type
end
JSON.parse(File.read(@cache_file)).as(Hash(String, JSON::Type))
end
end
puts Cache.new.cache(:something) { 10 } # => 10
puts Cache.new.cache(:something) { 'a' } # => 10
TL;DR I want to read a JSON file into a Hash(String => i_dont_care), replace a value under a given key name and serialize it to file again. How do I do that?
Upvotes: 0
Views: 564
Reputation: 3165
You can use use Hash(String, JSON::Type).from_json(File.read(@cache_file))
. Hopefully you can restrict the type of JSON::Type
down to something more sensible too. JSON::Any
and JSON.parse_raw
are very much a last resort compared to simply representing your schema using Hash
, Array
and custom types using JSON.mapping
.
Upvotes: 1
Reputation: 5661
JSON.parse
returns an JSON::Any, not a Hash so you can't cast it. You can however access the underlying raw value as JSON.parse(file).raw
and cast this as hash.
Then your code is basically working (I've fixed a few error): https://carc.in/#/r/28c1
Upvotes: 3