如何在Play 2.1中处理JSON解析中的可选字段

11

我正在使用新的Play 2.1-RC1框架,我有一个包含Option[]字段的类,就像这样:

import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
import play.api.libs.json.Format._
import play.api.libs.functional.syntax._

case class Test(name: String, value: Option[String])

object Test {
  implicit val testFormat = (
    (__ \ "name").format[String] and
    (__ \ "value").format[Option[String]] 
  )(Test.apply, unlift(Test.unapply))
  def fromJson(js: String): Test = {
    Json.fromJson[Test](Json.parse(js)).fold(
        valid   = { t => t},
        invalid = { e => {
          val missingField = (e(0)._1).toString.substring(1)
          val badJs = js.trim
          val newJs = badJs.substring(0, badJs.length()-1)+",\""+missingField+"\":null}"
          fromJson(newJs)
        }} 
    )
  }
}

我希望能够处理省略了可选的"value"数据的JSON字符串,例如:
val y = """{"name":"someone"}"""

我可以像验证步骤中展示的那样笨拙地重写json字符串,但是有没有更简单的模式可以用来为缺失的可选字段提供None?请注意,这种重写在嵌套结构或任何我无法简单地添加缺失字段的地方都不起作用。
2个回答

7
你可以简单地这样做:
import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Test(name: String, value: Option[String])

implicit val testFormat = Json.format[Test]

def hoge = Action(Json.parse.json) { request => 
    Json.fromJson[Test](request.body)
    ...
}

唯一的问题是JSON不是来自请求,而是来自WebSocket。 - NickStoughton
@NickStoughton Iteratee.foreach[JsValue](event => Json.fromJson[Test](event)) - sndyuk
@NickStoughton 仅供参考 https://github.com/playframework/Play20/blob/master/samples/scala/websocket-chat/app/models/ChatRoom.scala - sndyuk
2
谢谢!这很有帮助!但是,如果传入的JSON缺少格式化程序(读取器)所期望的字段,仍然存在问题。我已经更新了上面的示例,以展示一种解决方法。 - NickStoughton

6

OK ... so the answer is very simple. Use

fomatOpt()

对于可选字段。因此,测试格式化程序现在看起来像这样:

import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.json.Reads._
import play.api.libs.json.Writes._
import play.api.libs.json.Format._
import play.api.libs.functional.syntax._

case class Test(name: String, value: Option[String])

object Test {
  implicit val testFormat = (
    (__ \ "name").format[String] and
    (__ \ "value").formatOpt[String] 
  )(Test.apply, unlift(Test.unapply))

  def fromJson(js: String): Test = {
    Json.fromJson[Test](Json.parse(js)).fold(
      valid   = { t => t},
      invalid = { e => {
        println("BAD JSON!")
        null
      }} 
    )
  }
}

5
当使用Scala宏来注入Reads/Writes/Format的情况怎么办?例如,在您的情况下,我们可以只编写“implicit val testFormat = Json.format[Test]”。在这种情况下,您如何处理可选的JSON值? - visionary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接