我正试图弄清楚如何在我的Scala项目中正确地序列化MongoDB中的文档。我遇到的问题是,当我的文档中有一个数组字段时,我不知道该怎么办,也不知道如何在Scala中处理它。以下是MongoDB中的文档:
> db.injuries.findOne()
{
"_id" : ObjectId("5220ef71bbf8af333d000001"),
"team_id" : 86,
"league" : "NFC",
"team_name" : "Arizona Cardinals",
"players" : [
{
"player_id" : 9864,
"date" : "8/26/2013",
"position" : "TE",
"name" : "Rob Housler",
"injury" : "is doubtful for 9/8 against St. Louis",
"status" : "Doubtful",
"fantasy" : "",
"injured" : "True",
"type" : "ankle"
},
{
"player_id" : 11610,
"date" : "8/25/2013",
"position" : "G",
"name" : "Jonathan Cooper",
"injury" : "may be placed on injured reserve",
"status" : "Out",
"fantasy" : "",
"injured" : "True",
"type" : "leg"
},
{
"player_id" : 9126,
"date" : "4/3/2013",
"position" : "LB",
"name" : "Daryl Washington",
"injury" : "will be eligible to return on 10/6 against Carolina",
"status" : "Suspended",
"fantasy" : "",
"injured" : "True",
"type" : "four-game suspension"
}
],
"updated_at" : ISODate("2013-08-30T19:16:01.466Z"),
"created_at" : ISODate("2013-08-30T19:16:01.466Z")
}
>
现在我需要创建一个case类,这样我就可以为这个文档创建一个自定义序列化程序,并将其传递到客户端。我开始构建如下的案例类:
case class Injury(_id: ObjectId = new ObjectId, team_id: Int, team_name: String, league: String, players: List[????], created_at: Option[Date] = None, updated_at: Option[Date] = None, id: Option[ObjectId] = None )
我不一定想创建一个播放器案例类,因为播放器哈希在其他集合中看起来不同,这取决于上下文。我可能有一个球员阵列,比如说"时间表"集合,我不会在那里列出伤病数据。这并不是对玩家集合的实际引用,它只是一个带有哈希的列表,其中字段被命名为"玩家"。理想情况下,我可以弄清楚如何编写一个序列化程序,当这个团队的ID被请求时,它只会输出这个:
{
"team_id": 86,
"team_name": "Arizona Cardinals",
"players": [
{
"player_id": 9864,
"date": "8/26/2013",
"position": "TE",
"name": "Rob Housler",
"injury": "is doubtful for 9/8 against St. Louis",
"status": "Doubtful",
"fantasy": "",
"injured": "True",
"type": "ankle"
},
{
"player_id": 11610,
"date": "8/25/2013",
"position": "G",
"name": "Jonathan Cooper",
"injury": "may be placed on injured reserve",
"status": "Out",
"fantasy": "",
"injured": "True",
"type": "leg"
},
{
"player_id": 9126,
"date": "4/3/2013",
"position": "LB",
"name": "Daryl Washington",
"injury": "will be eligible to return on 10/6 against Carolina",
"status": "Suspended",
"fantasy": "",
"injured": "True",
"type": "four-game suspension"
}
]
}
为了能够派生到最终的JSON文档,我还需要做什么?我知道Salat可以处理case类的序列化。。但我不知道如何处理这里的玩家属性。这是我开始工作的一个序列化程序的开始,但仍然不知道如何将玩家地图放在这里:
class InjurySerializer extends CustomSerializer[Injury](format => ({
case JObject(
("id", JString(id)) ::
("team_id", JString(team_id)) ::
("team_name" , JString(team_name)) ::
("league" , JString(league)) :: Nil) =>
Injury(new ObjectId, team_id.asInstanceOf[Int], team_name.asInstanceOf[String], league.asInstanceOf[String])
}, {
case injury: Injury =>
JObject.apply(
"team_id" -> JInt(injury.team_id),
"team_name" -> JString(injury.team_name),
"league" -> JString(injury.league)
)
}))
然后我有一个简单的助手来检索所有文档:
object Injury {
def findAll = {
val results = InjuryDAO.findAll
results.map(grater[Injury].asObject(_)).toList
}
}
这很好,但不包括上面建议的玩家地图。
不支持数组。使它成为一个列表、一个seq、几乎任何其他类型的集合,您的文档就会正确地序列化和反序列化。
https://github.com/novus/salat/wiki/Collections
制作一个包含所有可能字段的玩家案例类,并使用默认参数来覆盖所有案例。
如果有太多不同的案例需要报道,那就是事情变得非常丑陋的时候。您实际上是在尝试将没有预期结构的数据反序列化为。。。究竟是什么?我还没有将Map[String, Any]
支持添加到主流萨拉特,尽管有一个悬而未决的拉入请求。
您可能需要在这里使用一些自定义序列化程序,我假设您有一个父对象的句柄-让我们调用该伤害
val playerRefs = injury.get("palyers")
var obj = MongoDBObject("list" -> playerRefs )
obj.as[MongoDBList]("list").toList.foreach {
value =>
val playerDef = value.asInstanceOf[BasicDBObject]
// Access values from player -
val name = playerDef.get("name")asInstanceOf[String]
// Build your case class
}