願望
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