2015-11-24 17 views
5

Tôi mới làm quen với Shapeless. Tôi có một lớp trợ giúp thúc đẩy 'Tự động Typeclass derivation' shapeless (https://gist.github.com/negator/fbbcd1b2ce9a85b762b7) để giúp tôi cư json đọc và viết.Không thể tìm thấy giá trị tiềm ẩn cho thông số lgen: shapeless.LabelledGeneric.Aux

import play.api.libs._ 
import json._ 

import shapeless.{ `::` => :#:, _ } 
import poly._ 

object SReads extends LabelledTypeClassCompanion[Reads] { 
    object typeClass extends LabelledTypeClass[Reads] { 

    def emptyProduct: Reads[HNil] = Reads(_ => JsSuccess(HNil)) 

    def product[F, T <: HList](name: String, FHead: Reads[F], FTail: Reads[T]) = Reads[F :#: T] { 
     case obj @ JsObject(fields) => 
     for { 
     head <- FHead.reads(obj \ name) 
     tail <- FTail.reads(obj - name) 
     } yield head :: tail 

     case _ => JsError("Json object required") 
     } 

    def project[F, G](instance: => Reads[G], to: F => G, from: G => F) = Reads[F](instance.map(from).reads) 

    def emptyCoproduct: Reads[CNil] = Reads[CNil](_ => JsError("CNil object not available")) 

    def coproduct[L, R <: Coproduct](
     name: String, 
     cl: => Reads[L], 
     cr: => Reads[R]) = Reads[L :+: R]{ js => 

     js match { 
     case js @ JsString(n) if n == name => cl.reads(js).map(Inl.apply) 
     case js @ _      => cr.reads(js).map(Inr.apply) 
     } 
    } 
    } 
} 

Đây là cách tôi đã sử dụng nó:

case class TrialMember(
    @Key("_id") var id: String, 
    var weeks: String, 
    var `type`: Option[String] = Some("email"), 
    var updatedDate: Date = DateTime.now.toDate 
) 

object TrialMemberDao extends ModelCompanion[TrialMember, String] { 
    def collection = mongoCollection("trial_member") 
    val dao = new SalatDAO[TrialMember, String](collection) {} 
    def emails() = dao.find(MongoDBObject("type" -> "email")).toList.map(_.id) 
    def domains() = dao.find(MongoDBObject("type" -> "domain")).toList.map(_.id) 
    def isTrialMember(userEmail: String): Boolean = { 
    val trialMembers = emails() // whitelisted emails 
    val trialDomains = domains() // whitelisted domains 
    trialMembers.contains(userEmail) || 
     trialDomains.filter(userEmail.contains(_)).headOption.isDefined 
    } 

} 

object TrialMember { 
    implicit val jsonWrites: Writes[TrialMember] = SWrites.deriveInstance 
    implicit val jsonReads: Reads[TrialMember] = SReads.deriveInstance 
} 

Nhưng sau khi nâng cấp lên SBT 0.13.8 and Play 2.4, bây giờ nó mang lại cho tôi lỗi này:

could not find implicit value for parameter lgen: shapeless.LabelledGeneric.Aux[T,LKV] 
[error] implicit val reads: Reads[TrialMember] = SReads.deriveInstance 
+0

Vui lòng cung cấp định nghĩa 'Foo' của bạn. Dường như nó hoạt động cho 'case class' của tôi – Odomontois

+0

@Odomontois Tôi đã chỉnh sửa câu hỏi. Xin vui lòng xem qua. – angelokh

Trả lời

1

Vấn đề là hơi hài hước, deriver typeclass của bạn được thực hiện hoàn hảo trong khi trình biên dịch không thể tìm thấy trường hợp Reads cho Option[String] nên được sử dụng cho trường type. Chỉ cần cung cấp mã của bạn với một cái gì đó giống như định nghĩa sau đây:

object optionFormats { 
    def noneReads[T]: Reads[Option[T]] = Reads(Function.const(JsSuccess(None))) 

    implicit def optFormat[T](implicit w: Writes[T], r: Reads[T]) = 
    Format[Option[T]](
     r.map[Option[T]](Some(_)).orElse(noneReads), 
     Writes(_.fold[JsValue](JsNull)(w.writes))) 
} 

Và sau đó trong bất kỳ mã chỉ

import optionFormats._ 

Và ví dụ của bạn nên được xây dựng như mong muốn.

+0

Tôi nên cung cấp dòng này ở đâu? Tôi đã sử dụng nó trong đối tượng TrialMember, và nó đang hoạt động. Nhưng sau đó tôi phải làm điều đó trong tất cả các lớp đối tượng. Có cách nào để sửa SReads thay thế không? – angelokh

+0

@Odomontois Bạn có biết tại sao việc nâng cấp lên sbt 0.13.8 và phát 2.4 có nghĩa là mã cũ sẽ không biên dịch được nữa không? – rmin

Các vấn đề liên quan