在Scala中使用QueryParamDecoder解码可选查询参数
我想解码Scala代码中的可选查询参数。我正在使用http4s。参数的形式为在Scala中使用QueryParamDecoder解码可选查询参数,scala,query-parameters,scala-cats,http4s,Scala,Query Parameters,Scala Cats,Http4s,我想解码Scala代码中的可选查询参数。我正在使用http4s。参数的形式为?part=35/43。最终目标是将这个分数存储为类型Part=(Int,Int),这样我们就可以将(35,43)作为元组在代码中进一步使用。我创建了一个对象,如: 现在,OptionalValidatingQueryParamDecoderMatcher在作用域中需要一个隐式的QueryParamDecoder[Part] 为此,我创建了一个隐式val,它需要检查我们是否有一个有效的分数,也就是说,两个字符都应该是数
?part=35/43
。最终目标是将这个分数存储为类型Part=(Int,Int)
,这样我们就可以将(35,43)
作为元组在代码中进一步使用。我创建了一个对象,如:
现在,OptionalValidatingQueryParamDecoderMatcher
在作用域中需要一个隐式的QueryParamDecoder[Part]
为此,我创建了一个隐式val,它需要检查我们是否有一个有效的分数,也就是说,两个字符都应该是数字(而不是a/1
或b/c
等),分数应该小于1(1/2
,5/8
等):
implicit val ev:QueryParamDecoder[部分]=
新的QueryParamDecoder[部分]{
def解码(
分区:QueryParameterValue
):ValidatedNel[ParseFailure,Part]={
val partAndPartitions=partition.value.split(“/”)
验证
.catchOnly[NumberFormatException]{
val part=partAndPartitions(0).toInt
val partitions=partAndPartitions(1).toInt
如果(
partAndPartitions.length!=2 | | | part>partitions | | | part好吧,最简单的方法是使用.catchOnly[Throwable]
(或者甚至直接使用QueryParamDecoder.fromUnfectast
),它将捕获任何错误
然而,我个人更愿意这样做:
(我现在无法编译代码,因此如果有一些拼写错误,我深表歉意)
隐式final val PartQueryParamDecoder:QueryParamDecoder[Part]=
QueryParamDecoder[String].emap{str=>
def故障(详细信息:字符串):或[ParseFailure,Part]=
左(右)键失败(
sanitized=“无效的查询参数部分”,
details=s“${str}”未正确格式化:${details}”
))
str.split(“/”).toList匹配{
案例aRaw::bRaw::Nil=>
(呼啸声,呼啸声)匹配{
案例(一些(a),一些(b))=>
右(第(一、二)部分)
案例=>
故障(详细信息=“部分分数部分不是数字”)
}
案例=>
失败(details=“它不对应于分数‘a/b’”)
}
}
非常有魅力!非常感谢!我连续两天都在努力解决这个问题。我正在查看emap
的文档,但无法清楚地了解何时使用decode
vsemap
。如果您能对此有所了解,那就太好了。:)@fandecode
是框架调用的方法,并且是从头开始编写Decorder
时唯一需要实现的方法。-emap
(和朋友们)是帮助从其他解码器
构建新的解码器
,因此您可以看到我所做的是假设记录已经可以解码为字符串
,然后尝试将该字符串
转换为部分
object OptionalPartitionQueryParamMatcher
extends OptionalValidatingQueryParamDecoderMatcher[Part]("part")
implicit val ev: QueryParamDecoder[Part] =
new QueryParamDecoder[Part] {
def decode(
partition: QueryParameterValue
): ValidatedNel[ParseFailure, Part] = {
val partAndPartitions = partition.value.split("/")
Validated
.catchOnly[NumberFormatException] {
val part = partAndPartitions(0).toInt
val partitions = partAndPartitions(1).toInt
if (
partAndPartitions.length != 2 || part > partitions || part <= 0 || partitions <= 0
) {
throw new IllegalArgumentException
}
(part, partitions)
}
.leftMap(e => ParseFailure("Invalid query parameter part", e.getMessage))
.toValidatedNel
}
}