【问题标题】:Play + Scala -> Validate IP Json dataPlay + Scala -> 验证 IP Json 数据
【发布时间】:2019-01-11 11:08:39
【问题描述】:

我正在尝试在 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 为同一类型,因为 OF​​ormat 可以读写。

如果我删除我的写入,当我将对象转换为 Json 字符串时,我的控制器中会出现异常。

尝试为此类型实现隐式写入或格式。

我宁愿使用 enumNameReads 和 enumNameWrites。

了解速记是很好的。我最终使用了我以前的解决方案,在转换为枚举之前将 json 字符串转换为小写。

建议使用首字母大写的类型命名,不带最后的“s” 用于复数(例如 ListType)。

我完全同意这一点。不幸的是,它是我现在不想重构的遗留代码的一部分。

【问题讨论】:

  • Json.reads 用于ipRangeStrReads

标签: json scala validation playframework


【解决方案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 可以读写。

我宁愿使用enumNameReadsenumNameWrites

implicit val r = Reads.enumNameReads(listTypes)
implicit val w = Writes.enumNameWrites[listTypes.type]

建议使用首字母大写的类型命名,复数不带最后的“s”(例如ListType)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    相关资源
    最近更新 更多