简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM