I'm trying to implement something like
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]
}
It does not compiles with an error
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]
According to Travis Brown the problem is "The generic derivation is designed to work with Shapeless's generic instances and expects the FieldType key to be a symbol." See discussion on Gitter.
My solution:
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
}
The encodeClaims function is basically a copy of the original function from circe, replacing constraint on the keys.
This answer can be used to implement another solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With