在Argonaut DecodeJson
特征中,有一个方法|||
用于将解码器链接在一起,以便选择第一个后续解码器。在DecodeResult
中也有类似的方法具有相同的效果。乍一看,好像其中一个是我们想要解码共同特征的多个子类型的东西。但是,我们如何实际做到这一点?
第一个问题是|||
的参数必须是DecodeJson
解码被调用者应该解码的类型的超类型(同样适用于DecodeResult
)。我希望这样的解码器能够解码常见超类型的所有子类型,所以这似乎是无限递归的一个秘诀!
我们可以在为超类型定义asInstanceOf
时使用以下丑陋的CodecJson
黑客来解决这个问题:
c => c.as[A] ||| c.as[Foo](implicitly[DecodeJson[B]].asInstanceOf[DecodeResult[Foo]])
然而,当解码两个以上的子类型时仍然存在问题。假设A
有B
,C
和Foo
个子类型。 现在是什么?我们如何为这个解码表达式添加另一种替代方案? .asInstanceOf[DecodeResult[AnyRef]]
将破坏解析结果的类型安全性(就好像我们此时已经没有丢弃类型安全性!)。然后我们很快就会用掉4,5或6种选择。
编辑:我很乐意接受使用Argonaut解码超过2个宽的子类型层次结构的替代方法。