[英]Scala Lift - Mongodb save data as json object
I have the following model 我有以下型号
class Recording private() extends MongoRecord[Recording] with ObjectIdPk[Recording] {
def meta = Recording
object data extends StringField(this, 50)
}
I'm currently saving a Json object as a string in the "data" field, I've used JsonObject field before but only with predefined object structures. 我目前正在将Json对象另存为“数据”字段中的字符串,我之前使用过JsonObject字段,但仅用于预定义的对象结构。 In this case the json object being saved can have any structure or data fields so a predefined data structure is not an option.
在这种情况下,要保存的json对象可以具有任何结构或数据字段,因此不能选择预定义的数据结构。
Say I have: 说我有:
{"name" : "James", "value" : "Hai!"}
Or 要么
{"result" : 1, "handle" : "lorem_ipsum"}
I need to be able to save both as a json object in the same field, "data". 我需要能够将两个字段另存为json对象,即“数据”。
Is there a way I can do this? 有办法吗?
Thanks in advance for any help, much appreciated :) 在此先感谢您的帮助,非常感谢:)
What might work for you is storing the data as a JValue
rather than a String
. 对您来说可能
JValue
是将数据存储为JValue
而不是String
。 You could use a JsonObjectField
wrapping a case class that contains a JValue
, which would allow an arbitrary structure, but it will give you an extra level of nesting in Mongo. 您可以使用
JsonObjectField
包裹一个包含JValue
的case类的案例类, JValue
将允许任意结构,但是它将为您提供Mongo的额外嵌套级别。 To get around that, how about creating a custom field just to hold a JValue
? 为了解决这个问题,如何创建一个仅包含
JValue
的自定义字段呢?
One stab at it: 一刺:
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))
}
...which looks a lot: all I've done is cut and paste from JValueObjectField
with one parameter removed and fixed at JValue
. ...这看起来很多:我所做的就是从
JValueObjectField
剪切并粘贴, JValueObjectField
了一个参数并固定为JValue
。 There may be a smarter way to do that. 可能有更聪明的方法可以做到这一点。
You can then use this in your model: 然后,您可以在模型中使用它:
object data extends JValueObjectField(this)
I'd populate it using the lift-json DSL: 我将使用lift-json DSL进行填充:
val json = ("name" -> "Bob") ~ ("result" -> 1)
Recording.createRecord.data(json).save
This will give you something in your MongoDB document like this: 这将为您在MongoDB文档中提供如下内容:
"data" : {
"name" : "Bob",
"result" : 1
}
BTW, the Lift Mailing list is a good way to get a better answer: that just happens to be where most of the Lift-related people seem to congregate. 顺便说一句, Lift Mailing列表是一个获得更好答案的好方法:这恰好是大多数与Lift相关的人员聚集的地方。
class Recording private() extends MongoRecord[Recording] with ObjectIdPk[Recording] {
def meta = Recording
object data extends JObjectField(this)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.