Raku HTTP 클라이언트 요청에서 JSON 추출
이 Raku 코드의 문제점을 이해하는 데 어려움이 있습니다.
웹 사이트에서 JSON을 가져 와서 JSON 내의 배열 (이 경우 Discourse 포럼의 최신 주제 제목)에있는 각 항목의 필드를 인쇄하고 싶습니다.
이것은 내가 작동 할 것으로 예상 한 코드이지만 실패했습니다.
use HTTP::UserAgent;
use JSON::Tiny;
my $client = HTTP::UserAgent.new; $client.timeout = 10;
my $url = 'https://meta.discourse.org/latest.json'; my $resp = $client.get($url);
my %data = from-json($resp.content); # I think the problem starts here. my @topics = %data<topic_list><topics>; say @topics.WHAT; #=> (Array) for @topics -> $topic {
say $topic<fancy_title>;
}
오류 메시지는 다음 say $topic<fancy_title>
줄 에서 나옵니다 .
Type Array does not support associative indexing.
in block <unit> at http-clients/http.raku line 18
해시 배열이기 때문에 $topic
로 작성되어야한다고 예상 %topic
했지만 작동하지 않습니다.
for @topics -> %topic {
say %topic<fancy_title>;
}
이에 대한 오류 메시지는 다음과 같습니다.
Type check failed in binding to parameter '%topic'; expected Associative but got Array ([{:archetype("regula...)
in block <unit> at http-clients/http.raku line 17
데이터를 검사하는 경우 배열이 아니라 해시 여야합니다. 나는 시도 @array
하지만이 변경 그래서, 즉 정확하지 알고 %topic
에 $topic
.
나는 마지막으로 추가하여 작업에있어 .list
정의하는 라인에 @topics
있지만, 때문에 나는, 왜 수정을 이해하지 못하는 @topics
입니다 (Array)
즉 추가 여부.
다음은 작동 코드입니다.
use HTTP::UserAgent;
use JSON::Tiny;
my $client = HTTP::UserAgent.new; $client.timeout = 10;
my $url = 'https://meta.discourse.org/latest.json'; my $resp = $client.get($url);
my %data = from-json($resp.content); # Adding `.list` here makes it work, but the type doesn't change. # Why is `.list` needed? my @topics = %data<topic_list><topics>.list; say @topics.WHAT; #=> (Array) # Why is it `$topic` instead of `%topic`?
for @topics -> $topic { say $topic<fancy_title>;
}
실패한 이유와이 작업을 수행하는 올바른 방법을 아는 사람이 있습니까?
답변
무슨 일이 일어 났는지 말할 때 배열의 배열을 만들었습니다.
my @topics = %data<topic_list><topics>;
이것은 이러한 모듈에 고유하지 않지만 배열 할당이있는 Raku 전반에 걸쳐 일반적입니다.
무슨 일이 일어나는지보기 위해 더 간단한 해시를 봅시다 :
my %x = y => [1,2,3];
my $b = %x<y>; my @b = %x<y>; say $b; # [1 2 3]
say @b; # [[1 2 3]]
문제는 배열 할당 (변수에시길이있을 때 사용됨 @
) 이 스칼라 컨테이너에있는 것처럼 %x<y>
단일 항목 으로 해석 한 다음 @b[0]
. 당신은 모듈 자체를 제어 할 수는 없지만, 당신이 말한다면 당신은 내 예에 차이를 볼 수 있습니다 my %x is Map = …
와 같은 Map
스칼라 용기에 물건을 올려 놓지 않지만, Hash
객체는 않습니다. Raku에게 단일 컨테이너가 아닌 단일 항목을 내용으로 처리하도록 지시하는 두 가지 방법이 있습니다.
- 바인드 배열
대신 사용은@b = %x<y>
, 당신이 사용@b := %x<y>
.@
-sigiled 변수에 바인딩하면 자동으로 컨테이너가 해제됩니다. - zen 연산자 사용
목록 / 해시 값이 하나로 취급되지 않도록하려면 zen 슬라이스를 사용하여 컨테이너가있는 경우 제거 할 수 있습니다. 이 작업을 수행 할 수 있습니다 중 하나를 할당에서 (@b = %x<y>[]
) 또는 상기for
루프 (for @b[] -> $b
). 그 주<>
,[]
그리고{}
효과적으로 동의어 관계없이 실제의 형태이다 - 대부분의 사람들은 이전과 일치 하나를 사용하십시오.
따라서 코드에서 다음을 수행 할 수 있습니다.
...
my %data = from-json($resp.content);
my @topics := %data<topic_list><topics>; # (option 1) binding
my @topics = %data<topic_list><topics><>; # (option 2) zen slice
for @topics -> $topic { say $topic<fancy_title>;
}
또는 옵션 3으로 루프에서
for @topics<> -> $topic { say $topic<fancy_title>;
}
.list
나머지 답변 이후에 추측 할 수 있듯이 문제를 해결 하는 이유 는 컨테이너에없는 새로운 목록을 반환하기 때문입니다.