願望
Int や Long などの プリミティブ型 ではなく 独自に定義した 値クラス などを Akka HTTP の route 定義で使いたい
(意図しない使用を回避するため)
独自に定義したクラス
final case class AccountId(value: Long) extends AnyVal
final case class Amount(value: Int) extends AnyVal
改善前
プリミティブ型なので、独自定義の型への変換を自分でやる必要がある
Path
pathPrefix("account" / LongNumber) { rawAccountId: Long =>
val accountId = AccountId(rawAccountId)
Parameter
parameter("amount".as[Int]) { rawAmount: Int =>
val amount = Amount(rawAmount)
改善後
Akka HTTPが型変換をするので、プリミティブ型は登場しない。
Path
PathMatcher1[T] の def map[R](f: T ⇒ R): PathMatcher1[R] を使用して型を変換
pathPrefix("account" / LongNumber.map(AccountId.apply)) { accountId: AccountId =>
各型の対応
-
T→Long -
R→AccountId
Parameter
NameReceptacle[T] の def as[B](unmarshaller: Unmarshaller[T, B]) を使用して型を変換
※ Unmarshaller[T, B] が必要なので、 Unmarshaller.strict[A, B](f: A ⇒ B): Unmarshaller[A, B] を使用して作成
implicit class ToNameUnmarshallerReceptacleEnhancements(name: String) {
def asAmount: NameUnmarshallerReceptacle[Amount] =
name.as[Int].as[Amount](Unmarshaller.strict(Amount.apply))
}
parameter("amount".asAmount) { amount: Amount =>
各型の対応
-
T→Int -
A→Int -
B→Amount