2

我有以下型号

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

    def meta = Recording

    object data extends StringField(this, 50)

}

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

说我有:

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

或者

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

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

有没有办法我可以做到这一点?

在此先感谢您的帮助,非常感谢:)

4

2 回答 2

0

可能对您有用的是将数据存储为 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
}

顺便说一句,电梯邮件列表是获得更好答案的好方法:这恰好是大多数电梯相关人员似乎聚集的地方。

于 2013-07-31T19:04:47.507 回答
0
class Recording private() extends MongoRecord[Recording] with ObjectIdPk[Recording] {

          def meta = Recording

          object data extends JObjectField(this)
}
于 2018-01-30T20:38:34.527 回答