简体   繁体   English

为递归数据结构定义`Codec`

[英]define `Codec` for recursive data structure

I have a class looking like this, 我有一堂这样的课,

case class Foo ( bar: Int, foos: Vector[Foo] )

to define a Codec[Foo] , I tried this, 定义一个Codec[Foo] ,我尝试了这个,

def fc = shapeless.Lazy((int32 ~~ vector(fc)).widenOpt( (Foo.apply _).tupled, Foo.unapply _ ))

But this did not work, since scodec throws StackOverflowError . 但这是行不通的,因为scodec抛出了StackOverflowError What is the right way of doing this ? 正确的做法是什么?

You'll need the scodec.codecs.lazily combinator to build recursive codecs (not shapeless.lazily ). 你需要的scodec.codecs.lazily组合子建递归编解码器(不shapeless.lazily )。 For example: 例如:

scala> def fc: Codec[Foo] = lazily((int32 :: vector(fc)).as[Foo])
fc: scodec.Codec[Foo]

scala> val res = fc.encode(Foo(1, Vector(Foo(2, Vector.empty)))).require
res: scodec.bits.BitVector = BitVector(64 bits, 0x0000000100000002)

scala> fc.decode(res)
res2: scodec.Attempt[scodec.DecodeResult[Foo]] = Successful(DecodeResult(Foo(1,Vector(Foo(2,Vector()))),BitVector(empty)))

In scodec 1.8.2 and prior, deriving this codec, instead of defining it explicitly, results in an error at compile time, due to the derivation continuing recursively forever. 在scodec 1.8.2及更高版本中,派生此编解码器而不是明确定义它,由于派生永远持续递归,因此在编译时会导致错误。 As of 1.8.3, this codec can be automatically derived without issue. 从1.8.3版开始,此编解码器可以自动派生而不会出现问题。

For an example of a recursive tree, see this example from scodec source . 有关递归树的示例,请参见scodec source中的示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM