如果要将其限制为仅处理单参数案例类,则不能使用
ProductTypeClass
. 其目的是归纳概括为
任意算术乘积。你想坚持算术1,所以你有冲突。你只要不用(小)样板自己写就行了
ProductTypeclass
object ShapelessJsonOFormat {
implicit def caseHListArity1[Head](implicit
headFmt: Lazy[OFormat[Head]] // Use Lazy in some places to get around the (incorrect) implicit divergence check in the compiler
): OFormat[Head :: HNil] = new OFormat[Head :: HNil] {
// ... serialize a Head :: HNil given headFmt.value: OFormat[Head]
}
implicit def caseGeneric[I, O](implicit
gen: Generic.Aux[I, O],
oFmt: Lazy[OFormat[O]]
): OFormat[I] = new OFormat[I] {
// ... serialize an I given a Generic I => O and oFmt.value: OFormat[O]
}
}
JSONObject
在arity抽象版本中。这是因为你正在使用
Generic
LabelledGeneric
,因此您没有能力为产品的元素提供字段名,因此它们在一个级别上混在一起。您可以正常使用
LabelledProductTypeClass
但事实并非如此
相当地
type OFormatObject[A] = OFormat[A] { def write(value: A): JsObject }
object ShapelessJsonOFormat {
implicit val caseHNil: OFormatObject[HNil] = new OFormat[HNil] {
override def read(json: JsValue) = HNil
override def write(value: HNil) = JsObject.empty
}
implicit def caseHCons[
HeadName <: Symbol,
Head,
Tail <: HList
](implicit
headFmt: Lazy[OFormat[Head]],
nameWitness: Witness.Aux[HeadName],
tailFmt: Lazy[OFormatObject[Tail]]
): OFormatObject[FieldType[HeadName, Head] :: Tail]
= new OFormat[FieldType[HeadName, Head] :: Tail] {
private val fieldName = nameWitness.value.name // Witness[_ <: Symbol] => Symbol => String
override def read(json: JsValue): FieldType[HeadName, Head] :: Tail = {
val headObj = json.asJsObject.get(fieldName)
val head = headFmt.read(headObj)
val tail = tailFmt.read(json)
field[HeadName](head) :: tail
}
override def write(value: FieldType[HeadName, Head] :: Tail): JsObject = {
val tail = tailFmt.write(value.tail)
val head = headFmt.write(value.head)
tail + JsObject(fieldName -> head) // or similar
}
}
implicit def caseLabelledGeneric[I, O](implicit
gen: LabelledGeneric.Aux[I, O],
oFmt: Lazy[OFormatObject[O]]
): OFormatObject[I] = new OFormat[I] {
override def read(json: JsValue): I = gen.from(oFmt.value.read(json))
override def write(value: I): JsObject = oFmt.value.write(gen.to(value))
}
}
OFormatObject
谈论
OFormat
s保证
write
JsObject
OFormatObject[HNil]
那只是
{ read = _ => HNil; write = _ => {} }
. 如果有一个序列化程序
Head
(
OFormat[Head]
Tail
(
OFormatObject[Tail]
),我们有一些单例类型,它表示
HeadName <: Symbol
,在中实现
Witness.Aux[HeadName]
),然后
caseHCons
OFormatObject[FieldName[HeadName, Head] :: Tail]
,看起来像
{ read = { headName: head, ..tail } => head :: tail; write = head :: tail => { headName: head, ..tail }
. 然后我们使用
caseLabelledGeneric
HList
FieldType
分为一般案例类。