[Raku] 如何處理 jsonlines 格式的檔案
作者:gugod 發佈於: ,更新於: #rakulang #jsonlinesjsonlines 是個利於處理大量同質資料的文字格式。基本上就是「每一行都是一個 JSON 文字格式的物件」而已。
例如說這樣就是個合格的 jsonlines 文字檔:
{"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]}
{"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]}
{"name": "May", "wins": []}
{"name": "Deloise", "wins": [["three of a kind", "5♣"]]}
只要每一行內容都是同質的,這種能夠內嵌複雜結構的檔案格式似乎比 CSV 稍微好用一點。至少,在碰到逗號、空白與引號時的處理規則就是依照 JSON 語法來處理就好。
要處理這種格式,就是要在讀檔時一行一行地讀,然後逐一交給某個能夠解析 JSON 文字的函式來將單行文字轉換成為物件。慣例上來說通常是轉換為 Hash 或 Array。
在 Raku 語裡面要一行一行讀檔就是在檔名字串後方加上 .IO.lines
造出一個迭代器。而既然有了迭代器,就可以使用 .map
:
use JSON::Fast;
my @records = "example.jsonl".IO.lines.map(&from-json);
如果是要反過來,把一個 Array 中的很多物件做成 jsonlines 文字,就是改用 to-json
。但是要注意,不能使其產生帶換行字符與排版用的空白字符,而必需採用所謂的「醜醜的」,把所有內容全部塞在一行之內的輸出效果。
為了方便起見,先利用 JSON::Fast
的 to-json
函式來定義一個 to-jsonline
函式,並使其能將物件 $o
轉換成一行 JSON 格式的文字,且在最後補上一個換行字符。
要將做好的文字全數輸出到某個檔案,就使用 .IO.spurt
。
整合起來範例如下:
use JSON::Fast;
sub to-jsonline ($o) {
to-json($o, :!pretty, :sorted-keys) ~ "\n"
}
my @records = [
{"name" => "Gilbert", "wins" => [["straight", "7♣"], ["one pair", "10♥"]]},
{"name" => "Alexa", "wins" => [["two pair", "4♠"], ["two pair", "9♠"]]},
{"name" => "May", "wins" => []},
{"name" => "Deloise", "wins" => [["three of a kind", "5♣"]]},
];
my $jsonlines = @records.map(&to-jsonline).join("");
"output.jsonl".IO.spurt($jsonlines);