【问题标题】:Scala Lift - Mongodb save data as json objectScala Lift - Mongodb 将数据保存为 json 对象
【发布时间】:2012-04-20 16:49:08
【问题描述】:

我有以下型号

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 对象。

有什么办法可以做到吗?

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

【问题讨论】:

  • 我对 MongoJsonObjectListField 的理解是,你需要在一个单独的对象中指定结构,我需要做的是将字段指定为 JsonObjectList 但能够让这些对象具有不同的字段名称。

标签: scala mongodb lift


【解决方案1】:

可能对您有用的是将数据存储为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 是获得更好答案的好方法:这恰好是大多数与电梯相关的人似乎聚集的地方。

【讨论】:

  • 非常感谢您抽出宝贵时间帮助我,我会仔细查看并让您知道我的进展情况。万事如意
【解决方案2】:
class Recording private() extends MongoRecord[Recording] with ObjectIdPk[Recording] {

          def meta = Recording

          object data extends JObjectField(this)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 2012-11-19
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 2020-12-18
    相关资源
    最近更新 更多