私はReactiveMongo 0.11.11をPlay 2.5に使用し、BSONDocumentをJsObjectに変換したいと考えています。JsObjectへのBSONDocumentとBSONDateTimeFormatをオーバーライド
ほとんどのBSONデータ型(String、Int ...)の場合、デフォルトではライブラリがその作業を行うために完全に正常です。 BSON型DateTime(BSONDateTime
)の場合、JSONプロパティの値は私に必要なフォーマットを与えません。私がしたいJSONは、このような日付の文字列表現である
{
"something": {
"$date": 1462288846873
}
}
:
日のためのJSONの値は、プロパティ名$date
でのJSObjectとその値としてミリ秒単位のUNIXタイムスタンプである
{
"something": "2016-05-03T15:20:46.873Z"
}
残念ながら、ライブラリ自体のすべてを書き換えたりコードを変更することなく、デフォルトの動作を上書きする方法はわかりません。私はそれが(source code)たまたまだと思うどこ
これは、次のとおりです。
val partialWrites: PartialFunction[BSONValue, JsValue] = {
case dt: BSONDateTime => Json.obj("$date" -> dt.value)
}
私のバージョンは、次のようになりなければならないでしょう:
val partialWrites: PartialFunction[BSONValue, JsValue] = {
case dt: BSONDateTime =>
JsString(Instant.ofEpochMilli(dt.value).toString)
}
は、このビットを無効にすることが可能ですか?
私は手動で特定を選ぶとき、私だけでなく、私はのJSObjectにBSONDocumentを変換する際JsValueにBSONDateTime変換は常に動作する必要があることに注意したいのですが...
import java.time.Instant
import play.api.libs.json._
import reactivemongo.bson._
import reactivemongo.play.json.BSONFormats.BSONDocumentFormat
object Experiment {
// Original document (usually coming from the database)
val bson = BSONDocument(
"something" -> BSONDateTime(1462288846873L) // equals "2016-05-03T15:20:46.873Z"
)
// Reader: converts from BSONDateTime to JsString
implicit object BSONDateTimeToJsStringReader extends BSONReader[BSONDateTime, JsString] {
def read(bsonDate: BSONDateTime): JsString = {
JsString(Instant.ofEpochMilli(bsonDate.value).toString)
}
}
// Reader: converts from BSONDateTime to JsValue
implicit object BSONDateTimeToJsValueReader extends BSONReader[BSONDateTime, JsValue] {
def read(bsonDate: BSONDateTime): JsValue = {
JsString(Instant.ofEpochMilli(bsonDate.value).toString)
}
}
// Read and print specific property "something" using the `BSONReader`s above
def printJsDate = {
val jsStr: JsString = bson.getAs[JsString]("something").get
println(jsStr) // "2016-05-03T15:20:46.873Z"
val jsVal: JsValue = bson.getAs[JsValue]("something").get
println(jsVal) // "2016-05-03T15:20:46.873Z"
}
// Use ReactiveMongo's default format to convert a BSONDocument into a JsObject
def printAsJsonDefault = {
val json: JsObject = BSONDocumentFormat.writes(bson).as[JsObject]
println(json) // {"something":{"$date":1462288846873}}
// What I want: {"something":"2016-05-03T15:20:46.873Z"}
}
}
を実験を作成しました既知の特性。これは、私の例のプロパティ "something"が任意の名前を持ち、サブドキュメントにも現れることを意味します。
BTW:私は通常、私のPlayプロジェクトでBSONコレクションを使用していますが、とにかくこのケースで違いはないと思います。
編集
私はWrites[BSONDateTime]
を提供しようとしましたが、残念ながらそれは使用されていないと私はまだ以前と同じ結果を得ます。コード:任意の型については
import java.time.Instant
import play.api.libs.json._
import reactivemongo.bson.{BSONDocument, BSONDateTime}
object MyImplicits {
implicit val dateWrites = Writes[BSONDateTime] (bsonDate =>
JsString(Instant.ofEpochMilli(bsonDate.value).toString)
)
// I've tried this too:
// implicit val dateWrites = new Writes[BSONDateTime] {
// def writes(bsonDate: BSONDateTime) = JsString(Instant.ofEpochMilli(bsonDate.value).toString)
// }
}
object Experiment {
// Original document (usually coming from the database)
val bson = BSONDocument("something" -> BSONDateTime(1462288846873L))
// Use ReactiveMongo's default format to convert a BSONDocument into a JsObject
def printAsJson = {
import reactivemongo.play.json.BSONFormats.BSONDocumentFormat
import MyImplicits.dateWrites // import is ignored
val json: JsObject = BSONDocumentFormat.writes(bson).as[JsObject]
//val json: JsValue = Json.toJson(bson) // I've tried this too
println(json) // {"something":{"$date":1462288846873}}
}
}
ありがとうございました。あなたが提案したようなWrites [BSONDateTime]を実装しましたが、無視されているようです。私の質問の編集を参照してください。私は何とかBSONDocumentFormatを使うからだと思っています。あなたはなにか考えはありますか? – Nick
'println(s" writer = $ {暗黙的に[Writes [BSONDateTime]]} ")' – cchantep
プリント: 'writer = play.api.libs.json.Writes $$ anon $ 6 @ b9c81b0' – Nick