播放框架 JSON 从空字符串读取到空列表



大家好,最近我在将 json 转换为我自己的数据模型时遇到了一个问题。

我有一个 json 格式的消息,其中可能包含一个空字符串:

{
"name" : "John Doe", 
"hobbies": ""
}

或爱好类型列表:

{
"name" : "John Doe", 
"hobbies": [{"name":"basketball"}]
}

以下是我在 scala play 框架中的案例类数据模型:

case class Person(name: String, hobbies: List[Hobby])
case class Hobby(name: String)

现在我正在使用默认的 json 格式化程序,但当然,当我们有空字符串作为值时,它不能很好地工作。

implicit val HobbyJson= Json.format[Hobby]
implicit val PersonJson = Json.format[Person]

如果hobbies具有空字符串,它将引发异常。当它是空字符串时,我想将其转换为空列表。我搜索了 Play 提供的文档,但找不到信息。谁能给出一些建议?

提前谢谢。

正如您所提到的,由于对hobbies的处理不一致,默认的Format宏在这里对您不起作用。所以你需要实现你自己的Reads[Person]- 这是我的做法:

object PersonJson {
implicit val hobbyConverter = Json.format[Hobby]
val personReads = new Reads[Person] {
override def reads(json: JsValue): JsResult[Person] = {
for {
personName  <- (json  "name").validate[String]
hobbies     <- (json  "hobbies").validate[JsValue]
} yield {
val maybeHobbyList = hobbies.validate[List[Hobby]].asOpt
Person(personName, maybeHobbyList.getOrElse(Nil))
}
}
}
implicit val personConverter = Format(personReads, Json.writes[Person])
}

这里要注意的关键是围绕整个事情,以JsResult理解和yield的礼貌。这为我们提供了所有必要的检查(例如name字段在那里并且是一个字符串,而hobbies字段在那里(。

yield块中的代码仅在我们有一些看起来非常接近Person的东西时才运行。然后我们可以安全地尝试将hobbies验证为List[Hobby],并将结果转换为Option[List[Hobby]]。如果它不起作用(因此它一定是一个字符串(,那将是一个None,因此我们根据需要将其默认为空列表。

感谢您@millhouse回答,它绝对有效。就像他说的那样,我们需要一个自定义Reads[Person]来正确转换它。

我还发布我的代码作为参考。

implicit val personJsonReads: Reads[Person] = (
(__  "name").read[String] and
(__  "hobbies").read[List[Hobby]].orElse(Reads.pure(List())) 
) (Person.apply _)

当值无法转换为List[Hobby]时,read[List[Hobby]].orElse(Reads.pure(List()))将生成空列表。

最新更新