Crystal 处理 json 已知格式但动态密钥的文件

Crystal handle json file of known format but dynamic keys

所以我有一个 JSON 格式有点已知的文件 { String => JSON::Type, ... }。所以它基本上是Hash(String, JSON::Type)类型的。但是当我尝试像这样从文件读取到内存时:JSON.parse(File.read(@cache_file)).as(Hash(String, JSON::Type)) 我总是得到一个例外:can't cast JSON::Any to Hash(String, JSON::Type)

我不确定如果我不能投射数据我应该如何处理它。

我基本上想做的是:

当然还有读取/写入文件...

这是我到目前为止的全部内容:

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 我想将一个 JSON 文件读入一个 Hash(String => i_dont_care) 中,替换给定键名下的一个值并将其再次序列化到文件中。我该怎么做?

JSON.parse returns 一个 JSON::Any,不是哈希,所以你不能转换它。但是,您可以访问基础原始值作为 JSON.parse(file).raw 并将其转换为散列。

那么你的代码基本上可以工作了(我已经修复了一些错误):https://carc.in/#/r/28c1

您可以使用Hash(String, JSON::Type).from_json(File.read(@cache_file))。希望您也可以将 JSON::Type 的类型限制为更合理的类型。与使用 HashArray 和使用 JSON.mapping.

的自定义类型简单地表示您的模式相比,JSON::AnyJSON.parse_raw 是最后的手段