Circe asJson 没有从抽象基础 class 编码属性
Circe asJson not encoding properties from abstract base class
假设我有以下抽象基 class:
package Models
import reactivemongo.bson.BSONObjectID
abstract class RecordObject {
val _id: String = BSONObjectID.generate().stringify
}
由以下具体案例扩展class:
package Models
case class PersonRecord(name: String) extends RecordObject
然后我尝试使用如下代码获取 JSON 字符串:
import io.circe.syntax._
import io.circe.generic.auto._
import org.http4s.circe._
// ...
val person = new PersonRecord(name = "Bob")
println(person._id, person.name) // prints some UUID and "Bob"
println(person.asJso) // {"name": "Bob"} -- what happened to "_id"?
如您所见,缺少继承自RecordObject
的属性 _id: String
。我希望内置编码器在这个用例中运行良好。我真的需要自己构建吗?
让我们看看编码器生成过程中发生了什么。 Circe 使用 shapeless 来派生它的编解码器,所以它足以检查 shapeless 解析成什么来回答你的问题。所以在菊石中:
@ abstract class RecordObject {
val _id: String = java.util.UUID.randomUUID.toString
}
defined class RecordObject
@ case class PersonRecord(name: String) extends RecordObject
defined class PersonRecord
@ import $ivy.`com.chuusai::shapeless:2.3.3`, shapeless._
import $ivy.$ , shapeless._
@ Generic[PersonRecord]
res3: Generic[PersonRecord]{type Repr = String :: shapeless.HNil} = ammonite.$sess.cmd3$anon$macro@1123d461
好的,所以它 String :: HNil
。很公平 - shapeless 所做的是提取构造函数中可用的所有字段以一种方式转换,如果转换另一种方式则通过构造函数将所有字段放回原处。
基本上所有类型class 派生都是这样工作的,所以你应该可以将 _id
作为构造函数传递:
abstract class RecordObject {
val _id: String
}
case class PersonRecord(
name: String,
_id: String = BSONObjectID.generate().stringify
) extends RecordObject
这将有助于类型 class 派生工作。如果你不能改变 PersonRecord
的样子……那么是的,你必须编写自己的编解码器。尽管我怀疑这会很容易,因为您使 _id
不可变并且不可能通过构造函数从外部设置,因此也很难使用任何其他方式实现。
假设我有以下抽象基 class:
package Models
import reactivemongo.bson.BSONObjectID
abstract class RecordObject {
val _id: String = BSONObjectID.generate().stringify
}
由以下具体案例扩展class:
package Models
case class PersonRecord(name: String) extends RecordObject
然后我尝试使用如下代码获取 JSON 字符串:
import io.circe.syntax._
import io.circe.generic.auto._
import org.http4s.circe._
// ...
val person = new PersonRecord(name = "Bob")
println(person._id, person.name) // prints some UUID and "Bob"
println(person.asJso) // {"name": "Bob"} -- what happened to "_id"?
如您所见,缺少继承自RecordObject
的属性 _id: String
。我希望内置编码器在这个用例中运行良好。我真的需要自己构建吗?
让我们看看编码器生成过程中发生了什么。 Circe 使用 shapeless 来派生它的编解码器,所以它足以检查 shapeless 解析成什么来回答你的问题。所以在菊石中:
@ abstract class RecordObject {
val _id: String = java.util.UUID.randomUUID.toString
}
defined class RecordObject
@ case class PersonRecord(name: String) extends RecordObject
defined class PersonRecord
@ import $ivy.`com.chuusai::shapeless:2.3.3`, shapeless._
import $ivy.$ , shapeless._
@ Generic[PersonRecord]
res3: Generic[PersonRecord]{type Repr = String :: shapeless.HNil} = ammonite.$sess.cmd3$anon$macro@1123d461
好的,所以它 String :: HNil
。很公平 - shapeless 所做的是提取构造函数中可用的所有字段以一种方式转换,如果转换另一种方式则通过构造函数将所有字段放回原处。
基本上所有类型class 派生都是这样工作的,所以你应该可以将 _id
作为构造函数传递:
abstract class RecordObject {
val _id: String
}
case class PersonRecord(
name: String,
_id: String = BSONObjectID.generate().stringify
) extends RecordObject
这将有助于类型 class 派生工作。如果你不能改变 PersonRecord
的样子……那么是的,你必须编写自己的编解码器。尽管我怀疑这会很容易,因为您使 _id
不可变并且不可能通过构造函数从外部设置,因此也很难使用任何其他方式实现。