Как разобрать этот симпатичный BSON в Scala?

В нашем проекте мы используем Scala и Reactivemongo. (Я очень новичок в обоих) Когда вы печатаете на консоли "симпатичный" Bson, это выглядит так:

{  _id: BSONObjectID("52b006fe0100000100d47242"),
desc: BSONString({"_id:"BSONObjectID(52af03a5010000010036194d),"desc:"BSONString(www.foo.com"hits),"domains:"["0:"BSONString(www.foo.com)"],"func:"BSONString(Count),"maxr:"BSONInteger(5),"props:"["]"} hits),
domains: [
0: BSONString(jsonString)
],
func: BSONString(Count),
maxr: BSONInteger(5),
props: [
]
}

Мне нужно иметь возможность анализировать его обратно с консоли в соответствующий класс Case.

Любая помощь, пожалуйста?


person Shany Tooper    schedule 17.12.2013    source источник
comment
какую версию реактивного монго вы используете?   -  person Jean    schedule 17.12.2013
comment
я... даже не знаю :/   -  person Shany Tooper    schedule 18.12.2013
comment
посмотрите файл Build.scala. он должен сказать, какую версию он тянет   -  person Ehud Kaldor    schedule 18.12.2013


Ответы (3)


взятый из шаблона активатора typesafe, вы можете просто использовать Json.format в качестве неявного val в объекте-компаньоне класса case (ReactiveMongo 0.9, scala 2.10.2). пример:

package models

import play.api.libs.json.Json
import reactivemongo.bson.BSONObjectID
import play.modules.reactivemongo.json.BSONFormats._

/**
 * A message class
 *
 * @param _id The BSON object id of the message
 * @param message The message
 */
case class Message(_id: BSONObjectID, message: String)

object Message {
  /**
   * Format for the message.
   *
   * Used both by JSON library and reactive mongo to serialise/deserialise a message.
   */
  implicit val messageFormat = Json.format[Message]
}

я использую его, и вы можете использовать больше параметров, если JSON знает, как их форматировать, или, если у вас есть члены, которые являются созданными вами классами case, если они имеют то же самое:

package models

import play.api.libs.json.Json
import reactivemongo.bson.BSONObjectID
import play.modules.reactivemongo.json.BSONFormats._

/**
 * A message class
 *
 * @param _id The BSON object id of the message
 * @param message The message
 */

case class Name(fName: String, lName: String, mInitial: String)

object Name {
  implicit val nameFormat = Json.format[Name]
}

case class Message(_id: BSONObjectID, message: String, name: Name)

object Message {
  /**
   * Format for the message.
   *
   * Used both by JSON library and reactive mongo to serialise/deserialise a message.
   */
  implicit val messageFormat = Json.format[Message]
}

я до сих пор не придумал, как это сделать, если у вас есть вспомогательные конструкторы или если вы реализуете применение (...) в компаньоне. однако компилятор предупредит вас об этом.

person Ehud Kaldor    schedule 17.12.2013
comment
Это на самом деле не отвечает на вопрос. Вы создали модуль форматирования json вместо bson. Тем не менее, в reactive-bson 0.9 есть макрос для создания средств форматирования bson, который делает то же самое. - person tmbo; 18.12.2013
comment
@ehud: если у вас есть вспомогательные конструкторы вашего собственного определения применения, вы должны создать новый экземпляр класса Format[A], проверьте stackoverflow.com/questions/20616677/ для того, что он может выглядеть (хотя в этом ответе я повторно использую макрос, чтобы избежать переписывания полного синтаксического анализа вручную, он должен дать вам подсказку) - person Jean; 18.12.2013

Вы можете проверить, как они это сделали, по этой ссылке в документации Reactivemongo: http://stephane.godbillon.com/2012/10/18/writing-a-simple-app-with-reactivemongo-and-play.-framework-pt-1.html

implicit object ArticleBSONReader extends BSONReader[Article] {
def fromBSON(document: BSONDocument) :Article = {
  val doc = document.toTraversable
  Article(
    doc.getAs[BSONObjectID]("_id"),
    doc.getAs[BSONString]("title").get.value,
    doc.getAs[BSONString]("content").get.value,
    doc.getAs[BSONString]("publisher").get.value,
    doc.getAs[BSONDateTime]("creationDate").map(dt => new DateTime(dt.value)),
    doc.getAs[BSONDateTime]("updateDate").map(dt => new DateTime(dt.value)))
  }
}
person Ayoub    schedule 17.12.2013
comment
Я могу ошибаться или ошибаться здесь, но, похоже, я получаю BSONDocument, в то время как у меня есть в основном просто одна строка, которая выглядит как рассматриваемый BSON. Как мне перейти от String к BSONDocument? - person Shany Tooper; 18.12.2013

Вот решение, которое я использую. Надеюсь поможет ->

    def bsonToString(bson: BSONDocument): String = {
        val bsonAsKeyValueList = bson.toMap.toList.map {
          case (key, document: BSONDocument) =>
            (key, bsonToString(document))
          case (key, value: BSONValue) =>
            (key, value.toString)
        }
        val bsonAsKeyValueStrings = bsonAsKeyValueList.map {
          case (key, value) =>
            s"""("${key}" -> ${value})"""
        }
        bsonAsKeyValueStrings.mkString("BSONDocument", ", ", "")
      }

person Carlos Saltos    schedule 04.06.2019