Playframework:如何将JSON绑定到包含地图的案例类?

时间:2013-12-09 18:56:42

标签: json scala playframework playframework-2.2

我正在使用Play框架2.2.1与Scala,我正在编写一个REST API,用户可以在其中设置部分非结构化数据。基本上,用户将POST JSON看起来像这样:

{
  "id": 1,
  "name": "MyObject",
  "properties": [
    "myFirstProperty": "Value 1",
    "mySecondProperty": "Value 2"
  ]
}

我希望它绑定到一个类似于:

的案例类
case class Preference(id: Long, name: String, properties: Map[String, String])

我希望利用Play的表单API,因此我可以免费获得一堆很好的验证选项,但我还没有找到一种直接的方法来做到这一点。理想情况下(至少在我看来),我可以沿着以下几行定义一个Form对象:

Form(
  mapping(
    "id" -> longNumber,
    "name" -> nonEmptyText(min = 5),
    "properties" -> map(nonEmptyText, nonEmptyText)
  )(Preference.apply)(Preference.unapply)
)

不幸的是,“地图(文字,文字)”是虚构的。有没有人使用表单API对此进行类似的绑定?如果是这样,怎么样?如果没有,我很好奇你用来验证的是什么。这一切都是手工完成的吗?

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

也许我误解了你的问题,但是the reads macro没有做你想做的事情?

import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val preferenceReads = Json.reads[Preference]

使用隐含的范围,您可以使用asasOptvalidate将您的JSON值转换为Preference(请参阅the Play ScalaJson docs

答案 1 :(得分:1)

据我所知,表单API和json支持并不意味着混合在一起。但这应该不是问题,因为您可以使用表单或json读取完成几乎所有验证。

import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._
import play.api.data.validation.ValidationError

val nonEmptyKeyValueMapReads = 
  filter[Map[String, String]](ValidationError("error.invalid"))(properties =>
    properties.keys.find(_.size == 0).isEmpty && properties.values.find(_.size == 0).isEmpty)

val preferencesReads =
  ((__ \ 'id).read[Long] and
    (__ \ 'name).read[String](minLength[String](5)) and
    (__ \ 'properties).read[Map[String, String]](nonEmptyKeyValueMapReads))(Preferences)

有几种方法可以实现您的属性,这是其中之一。定义读取后,您可以使用它来验证数据,例如: myJson.validate(preferencesReads)