Created
September 25, 2017 16:00
-
-
Save kolemannix/b22875b3bd9012e09223ffef7fe6e271 to your computer and use it in GitHub Desktop.
Wrapper-type Play JSON format automatic derivation using shapeless
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import play.api.libs.json._ | |
import shapeless.ops.hlist.IsHCons | |
import shapeless.{ Generic, HList, HNil } | |
/** | |
* Typeclass for automatically deriving a [play.api.libs.json.Format] instance for a type `A`. | |
* Instances will exist if A is a single-member case class containing a Formattable field | |
*/ | |
trait WrapperJsonFormat[A] { | |
def jsonFormat: Format[A] | |
} | |
object WrapperJsonFormat { | |
/** | |
* Summoner method | |
*/ | |
def apply[A](implicit instance: WrapperJsonFormat[A]): WrapperJsonFormat[A] = instance | |
/** | |
* Instance constructor method | |
*/ | |
def make[A](format: Format[A]): WrapperJsonFormat[A] = new WrapperJsonFormat[A] { | |
override def jsonFormat: Format[A] = format | |
} | |
def make[A](reads: Reads[A], writes: Writes[A]): WrapperJsonFormat[A] = make(Format(reads, writes)) | |
implicit def implyAllWrappers[A, R <: HList, H]( | |
implicit | |
gen: Generic.Aux[A, R], | |
isHCons: IsHCons.Aux[R, H, HNil], | |
formatH: Format[H] | |
): WrapperJsonFormat[A] = { | |
make[A]( | |
reads = Reads { jsValue => | |
val asH = jsValue.as[H](formatH) | |
/* Can I avoid this? How do I prove the value (asString :: HNil) <: R? */ | |
val asRepr = (asH :: HNil).asInstanceOf[R] | |
val a: A = gen.from(asRepr) | |
JsSuccess(a) | |
}, | |
writes = Writes { a => | |
val asR = gen.to(a) | |
val x: H = isHCons.head(asR) | |
formatH.writes(x) | |
} | |
) | |
} | |
} | |
// Usage | |
case class UserId(value: String) | |
implicit val format: Format[UserId] = WrapperJsonFormat[UserId].jsonFormat |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment