水晶句柄已知格式的json文件但动态键

时间:2017-06-21 22:56:55

标签: json crystal-lang

所以我有一个有点已知格式{ String => JSON::Type, ... }的JSON文件。所以它基本上是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)

如果我不能投射数据,我不确定如何处理数据。

我基本上想做的是:

  • 在字符串键
  • 下保存JSON ::类型数据
  • 用字符串键
  • 下的其他JSON :: Type数据替换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),替换给定键名下的值并再次将其序列化为文件。我该怎么做?

2 个答案:

答案 0 :(得分:3)

JSON.parse会返回JSON::Any,而不是哈希,因此您无法投射它。但是,您可以将基础原始值作为JSON.parse(file).raw访问,并将其转换为哈希值。

然后你的代码基本上正常工作(我修正了一些错误):https://carc.in/#/r/28c1

答案 1 :(得分:1)

您可以使用Hash(String, JSON::Type).from_json(File.read(@cache_file))。希望您可以将JSON::Type的类型限制为更合理的内容。与仅使用JSON::AnyJSON.parse_raw和使用Hash的自定义类型代表您的架构相比,ArrayJSON.mapping是最后的手段。