首页 文章

如何为JSON解析指定数据类型?

提问于
浏览
7

我有一个JSON响应,它是一个哈希数组:

[{"project" => {"id" => 1, "name" => "Internal"},
 {"project" => {"id" => 2, "name" => "External"}}]

我的代码如下所示:

client = HTTP::Client.new(url, ssl: true)
response = client.get("/projects", ssl: true)
projects = JSON.parse(response.body) as Array

这给了我一个数组,但似乎我需要对元素进行类型转换以实际使用它们,否则我得到 undefined method '[]' for Nil (compile-time type is (Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Type) | Array(JSON::Type))) .

我试过 as Array(Hash) ,但这给了我 can't use Hash(K, V) as generic type argument yet, use a more specific type .

如何指定类型?

2 回答

  • 10

    您必须在访问元素时强制转换这些元素:

    projects = JSON.parse(json).as(Array)
    project = projects.first.as(Hash)["project"].as(Hash)
    id = project["id"].as(Int64)
    

    http://carc.in/#/r/f3f

    但对于像这样的结构良好的数据,你最好使用 JSON.mapping

    class ProjectContainer
      JSON.mapping({
        project: Project
      })
    end
    
    class Project
      JSON.mapping({
        id: Int64,
        name: String
      })
    end
    
    projects = Array(ProjectContainer).from_json(json)
    project = projects.first.project
    pp id = project.id
    

    http://carc.in/#/r/f3g

    您可以在https://github.com/manastech/crystal/issues/982#issuecomment-121156428查看有关此问题的更详细说明

  • 3

    你继续在每一步中施展:

    projects = JSON.parse(response.body) as Array
    projects.each do |project|
      project = project as Hash
      project = project["project"] as Hash
      id = project["id"] as Int
      name = project["name"] as String
    end
    

    但是,如果您的API响应具有众所周知的结构,我强烈建议您使用JSON.mapping:https://crystal-lang.org/api/0.22.0/JSON.html#mapping-macro

相关问题