🫗

application/json-seq 対応の ストリーム を作成したので json-seq-stream として公開しました。

に公開

application/json-seq

皆さんは RFC7464 ... JavaScript Object Notation (JSON) Text Sequences は知っておられますでしょうか? mime-type だと application/json-seq です。

原文はここ

https://datatracker.ietf.org/doc/html/rfc7464

日本語訳はここ

https://tex2e.github.io/rfc-translater/html/rfc7464.html

で、これ 何が嬉しいかというと JSON の配列だと シリアライザーが有限処理するのでこの形式なら 無限生成を逐次処理しやすい…… ということです。

※ .NET だと JsonSerializerが Stream を元にして 無限非同期ジェネレータ (IAsyncEnumerable<T>) できるのですが、ここではおいておきます。

JavaScript だと asyncIterator という IFがありまます。これを使うと

for await (const item of items) 
{
  // TODO...
}

の様に非同期にデータを受け取ることができます。

過去作品だとこういうのもありましたね。

画像の読み込みが完了したら次のものを toplevel で for await して追加していくタイプのページング実装に async iterator を使っています。

いや、欄外なので

で、で、で RFC7464 という仕様がわかっていて、 使えそうな機能があるなら 実装しましょう。ということで実装しました。

本題

で、本題 application/json-seq 形式に対応した TransformStream こと JsonSequenceStream<T>json-seq-stream の default export および JsonSequenceStream として公開しました。

今回開発したのは次の機能です。

  • 文字列データから RS(0xe1) から始まって LF(0x0a) で終わるレコードを 抽出して 文字列として列挙する SequenceStream

  • json文字列のレコードをそれぞれ処理して T オブジェクトとして 列挙する JsonSequenceFormatStream<T>

  • 上記の機能を元に TextDecoderStreamSequenceStreamJsonSequenceFormatStream<T> する処理をまとめた JsonSequenceStream<T>

の三つです。基本的には 一番下の JsonSequenceStream<T> しか使わないつもりです。

リポジトリ

https://www.npmjs.com/package/json-seq-stream/v/1.0.5

次のコマンドでインストールできます。

npm i json-seq-stream@1.0.5

サンプル

使い方は次の様な感じです。

import { JsonSequenceStream } from "json-seq-stream";

type Value = {
    value: number;
};

const response = await fetch(url);
if (!response.ok) throw new Error();
const readable = response.body!
  .pipeThrough(new JsonSequenceStream<Value>());
for await (const value of readable) {
    console.log(value);
}

ちなみに JsonSequenceStream<T> を使わないのであれば次の様な感じです。

const readable = response.body!
  .pipeThrough(new TextDecoderStream())
  .pipeThrough(new SequenceStream())
  .pipeThrough(new JsonSequenceStream<Value>());

実装見たらまんまそうです。

https://github.com/juner/json-seq-stream/blob/bda11834464f86589b650d6349d021ac1b29eec1/src/JsonSequenceStream.ts#L7-L17

オプション

JsonSequenceStream<T> の コンストラクタの第一引数は JsonSequenceStreamOptions<T> 型を用意しています。

これは次のプロパティを持った Partial な型です。

参考文献

以上。

Discussion