使用scala Play框架处理多维JSON

时间:2013-04-13 22:16:02

标签: json scala playframework playframework-2.0

我正在尝试使用JSON请求将数据从客户端发送到服务器。 JSON请求的主体如下所示:

[
 [
  {"x":"0","y":"0","player":0},
  {"x":"0","y":"1","player":0},                      
  {"x":"0","y":"2","player":1}
 ],
 [
  {"x":"1","y":"0","player":0},
  {"x":"1","y":"1","player":2},
  {"x":"1","y":"2","player":0}
 ],
 [
  {"x":"2","y":"0","player":0},
  {"x":"2","y":"1","player":1},
  {"x":"2","y":"2","player":2}
 ]
] 

在服务器端,我想将Play 2框架的数据转换为Scala 2D列表,如下所示:

List(
 List(0,0,1),
 List(0,2,0),
 List(0,1,2)
)

这是3x3,但它可以变化,如50x50左右。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

它可能不完整(不知道你是否想要对方形矩阵约束进行建模)但这样的事情可能是一个好的开始:

首先,这是控制器(和模型)部件可以定义的内容

import play.api.libs.json.Json._
import play.api.libs.json._

type PlayerT = (String, String, Int)

implicit val playerTripleReads:Reads[PlayerT] = (
  (__ \ "x").read[String] and
  (__ \ "y").read[String] and
  (__ \ "player").read[Int]
  tupled
)

def getJson = Action(parse.json) { request =>
  request.body.validate[List[List[PlayerT]]].map{
    case xs => Ok(xs.mkString("\n"))
  }.recoverTotal{
    e => BadRequest("Detected error:"+ JsError.toFlatJson(e))
  }
}

在此版本中,您将获得一个列表,其中包含(String, String, Int)格式的已验证元组,该格式已使用PlayerT类型别名以节省一些输入内容。

正如您所看到的,读者是通过组合(使用and组合子)三个基本块“手动”创建的,并且使用tupled运算符将结果展平。

使用此解决方案,您现在可以使用这些元组,但由于_1_2_3的使用,IMO代码的可读性会受到影响一路上。

所以这里有一种不同的方法(实际上更容易......)解决了这个理智的编码问题,这将简单地定义一个用于模拟原子数据的案例类

case class Player(x:String, y:String, player:Int)

implicit val playerReads = Json.reads[Player]

def getJson = Action(parse.json) { request =>
  request.body.validate[List[List[Player]]].map{
    case xs => Ok(xs.mkString("\n"))
  }.recoverTotal{
    e => BadRequest("Detected error:"+ JsError.toFlatJson(e))
  }
}

请注意,由于在编译时使用了隐式的读者创建,读者将始终关注数据表示中的进一步更改,即case class的字段。

现在,您将能够使用xyplayer字段,而不是_1_2_3