-
-
Notifications
You must be signed in to change notification settings - Fork 111
Description
Alternatively: provide means to chain codecs (e.g. as fallbackTo).
Imagine a following use-case: an API where codecs for the entire ADT cannot be derived automatically (e.g., due to inconsistent discriminator policy of the API). Concrete example: Kraken websocket API. Two top-level discriminators: method or channel, result containing an optional channel field (which only then is to be treated as a discriminator for a subtree of messages):
https://docs.kraken.com/api/docs/websocket-v2/book#subscribe-request
{
"method": "subscribe",
"result": {
"channel": "book",
"depth": 10,
"snapshot": true,
"symbol": "ALGO/USD"
},
"success": true,
"time_in": "2023-10-06T17:35:55.219022Z",
"time_out": "2023-10-06T17:35:55.219067Z"
}https://docs.kraken.com/api/docs/websocket-v2/trade#subscribe-request
{
"method": "subscribe",
"result": {
"channel": "trade",
"snapshot": true,
"symbol": "MATIC/USD"
},
"success": true,
"time_in": "2023-09-25T09:21:10.428340Z",
"time_out": "2023-09-25T09:21:10.428375Z"
}https://docs.kraken.com/api/docs/websocket-v2/add_order#response
{
"method": "add_order",
"req_id": 123456789,
"result": {
"order_id": "AA5JGQ-SBMRC-SCJ7J7",
"order_userref": 100054
},
"success": true,
"time_in": "2023-09-21T14:15:07.197274Z",
"time_out": "2023-09-21T14:15:07.205301Z"
}https://docs.kraken.com/api/docs/websocket-v2/trade#snapshot-and-update-response
{
"channel": "trade",
"type": "snapshot",
"data": [
{
"symbol": "MATIC/USD",
"side": "buy",
"price": 0.5147,
"qty": 6423.46326,
"ord_type": "limit",
"trade_id": 4665846,
"timestamp": "2023-09-25T07:48:36.925533Z"
},
{
"symbol": "MATIC/USD",
"side": "buy",
"price": 0.5147,
"qty": 1136.19677815,
"ord_type": "limit",
"trade_id": 4665847,
"timestamp": "2023-09-25T07:49:36.925603Z"
}
]
}In short, a standard automatic top-down approach of deriving codecs (start with a top sealed trait, use discriminators at each nested level to find a first match of a subtype) fails short here.
A working solution: derive codecs for each message type separately (via JsonCodecMaker.make), then manually define codec for the parent sealed trait by combining codecs of the children with the firstOf policy. (see https://circe.github.io/circe/codecs/adt.html).
This is approach is currently difficult to implement, as the parent codec must actually dwell into the internals of child messages (see e948fb9, relates to #1266). Ideally, we would like to be able to combine child codecs as black boxes, without manually applying multiple low-level discriminating steps in the parent codec.