2015-09-13 14 views
6

mam odpowiedź JSON, który jest tablicą Hash:Jak określić typy danych dla parsowania JSON?

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

Mój kod wygląda następująco:

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

To daje mi tablicę, ale wydaje się, muszę typecast elementy faktycznie użyj ich inaczej, otrzymam undefined method '[]' for Nil (compile-time type is (Nil | String | Int64 | Float64 | Bool | Hash(String, JSON::Type) | Array(JSON::Type))).

Próbowałem as Array(Hash), ale to daje mi can't use Hash(K, V) as generic type argument yet, use a more specific type.

Jak określić typ?

Odpowiedz

8

Trzeba rzucić te jak masz dostęp do następujących elementów:

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

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

Ale dobrze ustrukturyzowanych danych, jak to jesteś lepiej z użyciem 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

Można zobaczyć nieco bardziej szczegółowe wyjaśnienie tego problemu w https://github.com/manastech/crystal/issues/982#issuecomment-121156428

+1

Pokonałeś mnie przez 1 minutę! – asterite

+0

pojawia się nowa składnia? https://play.crystal-lang.org/#/r/1uhw lub możesz użyć to_i i to_s FWIW. – rogerdpack

+0

To prawda, zaktualizowałem odpowiedź. –

3

nadal odlewania pod każdym kroku:

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 

Ale jeśli odpowiedź API ma dobrze znaną konstrukcję, zdecydowanie zalecamy użycie JSON .mapping: https://crystal-lang.org/api/0.22.0/JSON.html#mapping-macro