Scala Lift - Mongodb将数据保存为json对象

时间:2012-04-20 16:49:08

标签: scala mongodb lift

我有以下型号

class Recording private() extends MongoRecord[Recording] with ObjectIdPk[Recording] {

    def meta = Recording

    object data extends StringField(this, 50)

}

我目前正在将“Json”对象保存为“data”字段中的字符串,我之前使用过JsonObject字段,但只使用了预定义的对象结构。在这种情况下,保存的json对象可以包含任何结构或数据字段,因此预定义的数据结构不是一个选项。

说我有:

{"name" : "James", "value" : "Hai!"}

或者

{"result" : 1, "handle" : "lorem_ipsum"}

我需要能够将两者都保存为同一字段中的json对象“data”。

我有办法做到这一点吗?

提前感谢您的帮助,非常感谢:)

2 个答案:

答案 0 :(得分:0)

可能对您有用的是将数据存储为JValue而不是String。您可以使用JsonObjectField包装一个包含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
}
顺便说一下,Lift Mailing list是获得更好答案的好方法:恰好是与大多数与Lift有关的人聚集在一起的地方。

答案 1 :(得分:0)

class Recording private() extends MongoRecord[Recording] with ObjectIdPk[Recording] {

          def meta = Recording

          object data extends JObjectField(this)
}