我正在尝试验证Play Controller中POST请求中的JSON有效负载。我对Play&Scala世界非常陌生。
以下是我到目前为止获得的代码。无需任何输入验证即可正常工作。现在,我试图在IPRangeStr类的IP地址字段中添加验证,并遇到问题。我无法弄清楚对包含枚举的json列表的验证。
谢谢
object listTypes extends Enumeration {
type listTypes = Value
val TypeA= Value("TypeA")
val TypeB = Value("TypeB")
val Unknown = Value("Unknown")
def withNameWithDefault(name: String): Value =
values.find(_.toString.toLowerCase == name.toLowerCase()).getOrElse(Unknown)
}
case class IPRangeStr(firstIP: String, lastIP: String, listType: listTypes, action: String)
@Singleton
class DataController @Inject()(cc: ControllerComponents, actorSvc: IPDataActorService)(implicit exec: ExecutionContext) extends AbstractController(cc) {
implicit val listTypeEnumFormat = new Format[listTypes.listTypes] {
def reads(json: JsValue) = JsSuccess(listTypes.withNameWithDefault(json.as[String]))
def writes(listEnum: listTypes.listTypes) = JsString(listEnum.toString)
}
implicit val ipRangeStrReads: Reads[IPRangeStr] = Json.format[IPRangeStr]
implicit val ipRangeStrWrites = Json.writes[IPRangeStr]
def process = Action.async(parse.json[List[IPRangeStr]]) { implicit request =>
if(validationSuccess){
// process if validation successfull
Ok
} else {
BadRequest // validation error
}
} recoverWith {
case e: Exception =>
Future(InternalServerError)
}
}
}
#Edit-1 我基于@cchantep ans
的最终解决方案val validIPPattern: String = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])"
def isValidIP(ip:String) = ip.matches(validIPPattern)
implicit val ipRangeStrReads: Reads[IPRangeStr] =
Json.format[IPRangeStr].filter { ipR =>
isValidIP(ipR.firstIP) && isValidIP(ipR.lastIP) //true or false, according validation of ipR
}
implicit val ipRangeStrWrites = Json.writes[IPRangeStr]
使用Json.format时,不需要再次调用 Json.write具有相同的类型,因为OFormat能够读取和写入。
如果删除写操作,则在将对象转换为Json字符串时,控制器中会出现异常。
尝试为此类型实现隐式的Writes或Format。
我宁愿使用enumNameReads和enumNameWrites。
很高兴知道速记。我最终使用了以前的解决方案,该解决方案在转换为枚举之前将json字符串转换为小写。
建议使用开头的大写字母来命名类型,不带最后的“ s” 表示复数形式(例如ListType)。
我完全同意这一点。不幸的是,它是遗留代码的一部分,我现在不想重构。
答案 0 :(得分:1)
函数.filter
可用于Reads
。
implicit val ipRangeStrReads: Reads[IPRangeStr] =
Json.format[IPRangeStr].filter { ipR =>
true // or false, according validation of ipR
}
使用
Json.format
时,不需要再次调用同一类型的Json.write
,因为OFormat
可以读写。
我宁愿使用enumNameReads
和enumNameWrites
。
implicit val r = Reads.enumNameReads(listTypes)
implicit val w = Writes.enumNameWrites[listTypes.type]
建议使用开头的大写字母来命名类型,而不要使用以复数结尾的“ s”(例如
ListType
)。