2016-03-09 5 views
5

Ich versuche, so etwas wie Circe allgemeine Codec-Ableitung für Datensätze mit Objektschlüssel

object Claims { 
    import shapeless._ 
    import shapeless.labelled.FieldType 
    import io.circe._ 
    import io.circe.generic.semiauto._ 
    import java.util.UUID 

    type ClaimOf[V] = FieldOf[V] 
    object iss extends ClaimOf[String] 
    object subj extends ClaimOf[String] 
    object aud extends ClaimOf[Set[String]] 
    object client_id extends ClaimOf[UUID] 

    implicit val encoder = 
    deriveEncoder[FieldType[iss.type, String] :: FieldType[subj.type, String] :: HNil] 
} 

zu implementieren Es ist kompiliert nicht mit einem Fehler error: could not find implicit value for parameter encode: shapeless.Lazy[io.circe.generic.encoding.DerivedObjectEncoder[shapeless.::[shapeless.labelled.FieldType[Claims.iss.type,String],shapeless.::[shapeless.labelled.FieldType[Claims.subj.type,String],shapeless.HNil]]]] deriveEncoder[FieldType[iss.type, String] :: FieldType[subj.type, String] :: HNil]

Antwort

3

zu Travis Brown das Problem laut ist „Der Gattungs Derivation wurde entwickelt, um mit generischen Instanzen von Shapeless zu arbeiten, und erwartet, dass der Feldtyp-Schlüssel ein Symbol ist. " See discussion on Gitter.

Meine Lösung:

object Claims { 
    import shapeless._ 
    import shapeless.labelled.FieldType 
    import io.circe._ 
    import io.circe.syntax._ 
    import io.circe.generic.semiauto._ 
    import io.circe.generic.encoding.DerivedObjectEncoder 
    import java.util.UUID 

    abstract case class ClaimOf[V](name: String) extends FieldOf[V] 

    object iss extends ClaimOf[String]("iss") 
    object subj extends ClaimOf[String]("subj") 
    object aud extends ClaimOf[Set[String]]("aud") 
    object client_id extends ClaimOf[UUID]("client_id") 

    implicit final def encodeClaims[K, H, T <: HList](implicit key: Witness.Aux[K], 
                 claim: K <:< ClaimOf[H], 
                 encodeHead: Lazy[Encoder[H]], 
                 encodeTail: Lazy[DerivedObjectEncoder[T]] 
                ): DerivedObjectEncoder[FieldType[K, H] :: T] = 
    new DerivedObjectEncoder[FieldType[K, H] :: T] { 
    final def encodeObject(a: FieldType[K, H] :: T): JsonObject = a match { 
     case h :: t => 
     (key.value.name -> encodeHead.value(h)) +: encodeTail.value.encodeObject(t) 
    } 
    } 

    val encoder = deriveEncoder[FieldType[iss.type, String] :: FieldType[subj.type, String] :: HNil] 

    val rec = (iss ->> "issuer") :: (subj ->> "subject") :: HNil 

    val json = rec.asJson.spaces2 
} 

Die encodeClaims Funktion ist im Grunde eine Kopie der ursprünglichen Funktion von circe, auf der Taste Zwang ersetzen.

This answer kann verwendet werden, um eine andere Lösung zu implementieren.