JSON को एक Raku HTTP क्लाइंट अनुरोध से निकालना
मुझे यह समझने में परेशानी हो रही है कि इस Raku कोड में क्या गलत है?
मैं JSON को एक वेबसाइट से लाना चाहता हूं, और JSON के भीतर एक सरणी में प्रत्येक आइटम से एक फ़ील्ड प्रिंट करता हूं (इस मामले में किसी भी प्रवचन मंच से नवीनतम विषयों के शीर्षक)।
यह वह कोड है जिसकी मुझे काम करने की उम्मीद थी, लेकिन यह विफल रहा:
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
वस्तुओं है। एक ही कंटेनर के बजाय एकल आइटम को अपनी सामग्री के रूप में इलाज करने के लिए राकु को बताने के दो तरीके हैं।
- सरणी
का उपयोग करने के बजाय बाँधें@b = %x<y>
, आप उपयोग करते हैं@b := %x<y>
। बाइंडिंग@
-sigiled चर स्वचालित रूप से decontainerizes। - ज़ेन ऑपरेटर का उपयोग करें
जब आप किसी सूची / हैश मान को एक के रूप में माना जाने की संभावना से बचना चाहते हैं, तो आप किसी भी कंटेनर को हटाने के लिए ज़ेन स्लाइस का उपयोग कर सकते हैं यदि यह वहां होता है। यह किया जा सकता है या तो काम पर (@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
चीजों को ठीक करता है - जैसा कि आप शायद शेष उत्तर के बाद समझ सकते हैं - यह है कि यह एक ताजा सूची देता है जो एक कंटेनर में नहीं है।