【问题标题】:Scalaz validation with Argonaut使用 Argonaut 进行 Scalaz 验证
【发布时间】:2015-04-13 01:16:55
【问题描述】:

我有一个案例类和伴随对象:

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 decodeValidation 方法,该方法返回一个 Validation[String, X]。不幸的是,我需要一个错误列表。

有什么建议吗?

【问题讨论】:

  • 我不确定有没有好的答案,但您始终可以使用decodeValidationjdecode2L((a: String, b: Int) => (a, b))("name", "age") 来获取一个元组,然后切换到ValidationNel
  • 你有例子吗?抱歉,我真的是 Scala 新手。

标签: json scala scalaz argonaut


【解决方案1】:

我添加这个作为答案是因为这是我想办法解决问题的方法,但我有一段时间没有密切关注 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)
}

然后我将 JSON 解码为 (String, Int) 对,然后再创建 Person

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 一个)。在这种情况下进行错误累积工作会复杂得多。

与此相关的是,您还会在Validation 上看到关于flatMap 的弃用警告,您可以将其视为在绑定不会发生累积的提醒。你可以通过导入scalaz.Validation.FlatMap._告诉编译器你理解的。

【讨论】:

  • 谢谢,这很好用。我没有收到弃用警告,我收到了错误。导入 FlatMap._ 修复了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多