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

タイプを指定するにはどうすればよいですか?

4

2 に答える 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で確認できます。

于 2015-09-13T18:06:34.473 に答える
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

于 2015-09-13T18:08:27.823 に答える