可能对您有用的是将数据存储为 aJValue
而不是String
. 您可以使用JsonObjectField
包装一个包含 a 的案例类JValue
,这将允许任意结构,但它会在 Mongo 中为您提供额外的嵌套级别。为了解决这个问题,如何创建一个自定义字段来保存一个JValue
?
一击必杀:
abstract class JValueObjectField[OwnerType <: BsonRecord[OwnerType]](rec: OwnerType)
extends Field[JValue,OwnerType]
with MandatoryTypedField[JValue]
with MongoFieldFlavor[JValue] {
def owner = rec
def defaultValue = JNothing
def toForm: Box[NodeSeq] = Empty
implicit val formats = owner.meta.formats
def asJValue: JValue = valueBox openOr JNothing
def setFromJValue(jv: JValue): Box[JValue] = Full(jv)
def setFromString(in: String): Box[JValue] = tryo(JsonParser.parse(in)) match {
case Full(jv: JValue) => setFromJValue(jv)
case f: Failure => setBox(f)
case other => setBox(Failure("Error parsing String into a JValue: "+in))
}
def setFromAny(in: Any): Box[JValue] = in match {
case dbo: DBObject => setFromDBObject(dbo)
case value: JValue => setBox(Full(value))
case Some(value: JValue) => setBox(Full(value))
case Full(value: JValue) => setBox(Full(value))
case (value: JValue) :: _ => setBox(Full(value))
case s: String => setFromString(s)
case Some(s: String) => setFromString(s)
case Full(s: String) => setFromString(s)
case null|None|Empty => setBox(defaultValueBox)
case f: Failure => setBox(f)
case o => setFromString(o.toString)
}
def asDBObject: DBObject = JObjectParser.parse(asJValue.asInstanceOf[JObject])
def setFromDBObject(dbo: DBObject): Box[JValue] =
setFromJValue(JObjectParser.serialize(dbo))
}
...看起来很多:我所做的只是剪切和粘贴JValueObjectField
一个参数,删除并固定在JValue
. 可能有更聪明的方法来做到这一点。
然后,您可以在模型中使用它:
object data extends JValueObjectField(this)
我会使用lift-json DSL 填充它:
val json = ("name" -> "Bob") ~ ("result" -> 1)
Recording.createRecord.data(json).save
这将在 MongoDB 文档中为您提供如下内容:
"data" : {
"name" : "Bob",
"result" : 1
}
顺便说一句,电梯邮件列表是获得更好答案的好方法:这恰好是大多数电梯相关人员似乎聚集的地方。