簡體   English   中英

使用Argonaut進行Scalaz驗證

[英]Scalaz validation with Argonaut

我有一個案例類和同伴對象:

case class Person private(name: String, age: Int)

object Person {

  def validAge(age: Int) = {
    if (age > 18) age.successNel else "Age is under 18".failureNel
  }

  def validName(name: String) = {
    name.successNel
  }

  def create(name: String, age: Int) = (validAge(age) |@| validName(name))(Person.apply)

}

我想使用Argonaut解析一些JSON並以列表形式返回Person或一些錯誤。 所以我需要:

  1. 從字符串中讀取JSON,並驗證字符串格式正確
  2. 將JSON解碼為Person或錯誤字符串列表。

我想以某種形式返回錯誤,我可以將其轉換為更多的JSON,例如:

{
  errors: ["Error1", "Error2"]
}

我首先嘗試使用Argonauts的encodeValidation方法,該方法返回Validation [String,X]。 不幸的是,我需要一個錯誤列表。

有什么建議么?

我將其添加為答案,因為這是我從頭開始解決問題的方法,但是一段時間以來我一直沒有與Argonaut開發保持緊密聯系,我很樂意聽到有一個問題更好的方法。 首先進行設置,它可以解決您的一些小問題,並為名稱添加有效條件,以使后面的示例更加有趣:

import scalaz._, Scalaz._

case class Person private(name: String, age: Int)

object Person {
  def validAge(age: Int): ValidationNel[String, Int] =
    if (age > 18) age.successNel else "Age is under 18".failureNel

  def validName(name: String): ValidationNel[String, String] =
    if (name.size >= 3) name.successNel else "Name too short".failureNel

  def create(name: String, age: Int) =
    (validName(name) |@| validAge(age))(Person.apply)
}

然后在創建Person之前(String, Int)將JSON解碼為(String, Int)對:

import argonaut._, Argonaut._

def decodePerson(in: String): ValidationNel[String, Person] =
  Parse.decodeValidation(in)(
    jdecode2L((a: String, b: Int) => (a, b)
  )("name", "age")).toValidationNel.flatMap {
    case (name, age) => Person.create(name, age)
  }

接着:

scala> println(decodePerson("""{ "name": "", "age": 1 }"""))
Failure(NonEmptyList(Name too short, Age is under 18))

請注意,這不會在更復雜的情況下累積錯誤-例如,如果name字段的值是數字並且age1 ,那么您只會得到一個錯誤( name one)。 在這種情況下使錯誤累積有效得多。

相關地,您還會在Validation上看到關於flatMap的棄用警告,可以將其視為提醒,不會在綁定期間發生累積。 您可以通過導入scalaz.Validation.FlatMap._告訴編譯器您了解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM