What might work for you is storing the data as a JValue
rather than a 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. To get around that, how about creating a custom field just to hold a 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
. 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:
val json = ("name" -> "Bob") ~ ("result" -> 1)
Recording.createRecord.data(json).save
This will give you something in your MongoDB document like this:
"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.