使用Scala Play框架处理多维JSON [英] Handle multidimensional JSON with scala Play framework
问题描述
我正在尝试使用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左右那样可变.
感谢您的帮助.
它可能是不完整的(不知道您是否也要对方阵约束建模),但是类似的事情可能是一个不错的开始:>
首先,这是控制器(和模型)部分可以定义的内容
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
运算符将结果弄平.
使用此解决方案,您现在可以按需使用这些元组了,但是IMO代码由于在使用过程中使用_1
,_2
和_3
会导致可读性差.
因此,这是解决此合理编码问题的另一种方法(实际上甚至更容易...),这将简单地定义一个案例类,以对您的原子数据进行建模
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
的字段.
现在,您将能够使用x
,y
和player
字段,而不是_1
,_2
和_3
.
I am trying to send data from the client to the server using a JSON request. The body of the JSON request looks like this:
[
[
{"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}
]
]
On server side I would like to transform data with Play 2 framework to Scala 2D list like this:
List(
List(0,0,1),
List(0,2,0),
List(0,1,2)
)
this is 3x3 but it can be variable like 50x50 or so.
Thanks for any help.
It might be incomplete (don't know if you want to modelize the square matrix contraint as well) but something like that could be a good start:
First here is what the controller (and model) part can define
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))
}
}
In this version, you'll get a list of list holding validated tuples of the form (String, String, Int)
which has been aliased with the PlayerT
type to save some typing.
As you may saw, the reader as been created "by-hand" by composing (using the and
combinator) three basic blocks and the result is flattened using the tupled
operator.
With this solution you're now on track to play with those tuples, but IMO the code will suffer from bad readability, because of the usage of _1
, _2
and _3
along the way.
So here is a different approach (which is in fact even easier...) that tackles this problem of sane coding, this will simply defined a `case class that models your atomic data
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))
}
}
Note that, the reader will always follow further changes in your data representation, that is the case class
's fields thanks to the use of the implicit creation of the reader at compile time.
Now, you'll be able to use x
, y
and player
fields rather than _1
, _2
and _3
.
这篇关于使用Scala Play框架处理多维JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!