Argonaut を使用して、リモート JSON プロバイダーからオブジェクトを解析しています。API には 2 種類のエンドポイントがあります。1 つは、URL での従来の REST 要求と、単一の JSON オブジェクトの応答です。このタイプのエンドポイントで Argonaut を使用すると、複雑な JSON 戻りオブジェクトを簡単に解析できます。
私の問題は、プロバイダーのストリーミング エンドポイントにあり、これは特定のエンドポイントの制限付きセットの JSON からランダムな JSON オブジェクトを返します。オブジェクトは、サイトで発生した順序で返され、約 20 の異なるオブジェクトのいずれかがいつでも返される可能性があります。
API を調べてみると、Argonaut を使用してこの問題に対処する方法が見つかりません。API はすべて、次のオブジェクトの型を予測できない環境では困難な、型のパラメーター化を必要とするようです。1 つのオプションは、JSON の各ブロックの最初の数文字に基づいて異なるコーデックにディスパッチすることですが、これは、JSON 文字列をパーサーに送信し、代わりにオブジェクトを取得するという目標を台無しにします。
私がこれまでに見つけた最高のものは、すべてのトップレベルのケースクラスが空を拡張することですtrait
:
implicit def ModelDecodeJson: DecodeJson[Model] =
DecodeJson(c =>
c.as[ModelSubclassA].asInstanceOf[DecodeResult[Model]]
||| c.as[ModelSubclassB].asInstanceOf[DecodeResult[Model]]
// many more here!
)
残念なことに、ModelSubclassA
両方ModelSubclassB
とも他のケース クラスにいくつかの関連付けがあり、この例はコンパイルされますが、実行時にこれらのサブタイプを解析しようとすると失敗します。全体として、返されるデータの階層を形成する数十のケース クラスがあります。
私もこれをfor
理解して構築しようとしましたが、運もありません。
ここでより良いパターンをアドバイスできる人はいますか?
アップデート
以下はよりスケーラブルなパターンを持っているようですが、型は連携していません:
implicit def ModelDecodeJson: DecodeJson[Model] =
DecodeJson(c =>
(c.as[ModelSubclassA] ||| c.as[ModelSubclassB]).asInstanceOf[DecodeResult[Model]]
)
エラー:(10, 17) タイプが一致しません。見つかった:argonaut.DecodeResult[ModelSubclassB] 必須:argonaut.DecodeResult[モデルでシリアライズ可能な製品] 注:ModelSubclassB <:モデルでシリアライズ可能な製品ですが、クラスDecodeResultはタイプAで不変です。代わりにAを+Aとして定義したい場合があります. (SLS 4.5) ||| c.as[ModelSubclassB]).asInstanceOf[デコード結果[モデル]] ^
そのため、ソースを調べ始めたところ、バージョン 6.2-M1 のエラーで示唆されているように、 の定義がDecodeResult
を含むように変更されていることに気付きました。+A
残念ながら、そのバージョンにアップグレードすると、すべてのModel
サブクラス コーデックがあいまいな暗黙に変わりましたが、これは理にかなっています。
うーん...