我使用Argonaut解析来自远程JSON提供程序的对象。API有两种端点类型,一种是URL处的传统REST请求和单个JSON对象的响应。我能够轻松地在这种类型的端点上使用Argonaut解析复杂的JSON返回对象。
我的问题在于提供者的流端点,它从给定端点的一组有界JSON返回随机JSON对象。这些对象按照它们在站点上出现的顺序返回,大约20个不同对象中的任何一个都可以在任何时候返回。
通过使用API,我无法找到一种使用Argonaut来处理这个问题的方法。API似乎都需要类型参数化,这在无法预测下一个对象类型的环境中是很困难的。一种选择是根据每个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.DecodeResultModelSubclassB必需:使用Model备注可序列化的argonaut.DecodeResultProduct : ModelSubclassB <:Product,但类DecodeResult在类型A中是不变的。您可能希望将A定义为+A。(SLS4.5)\x{e76f}\x{e76f} c.asModelSubclassB).asInstanceOf[DecodeResultModel] ^
因此,我开始查看源代码,并意识到DecodeResult的定义已更改为包含+A,正如6.2-M1版本中的错误所暗示的那样。不幸的是,升级到该版本后,所有的Model子类代码都变成了含糊不清的隐含,这是有意义的。
呃..。
发布于 2016-02-24 21:09:33
这一问题的答案需要两部分:
Model特性被编解码器用来解析度。如果它也用作返回类型,则引入编译器无法明确解析的递归定义。match中的提取器来获得其中的实际值。https://stackoverflow.com/questions/35519516
复制相似问题