title: BSONDocument to JsObject and override BSONDateTimeFormat
body: <p>I use ReactiveMongo 0.11.11 for Play 2.5 and want to convert a BSONDocument to a JsObject.</p>
  
  <p>For most BSON data types (String, Int...) the defaults are perfectly fine to let the library do the job. For BSON type DateTime (<code>BSONDateTime</code>) the value of the JSON property does not give me the format I need.</p>
  
  <p>The JSON value for a Date is a JsObject with property name <code>$date</code> and a UNIX timestamp in milliseconds as its value:</p>
  
  <pre><code>{
      "something": {
          "$date": 1462288846873
      }
  }
  </code></pre>
  
  <p>The JSON I want is a String representation of the Date like this:</p>
  
  <pre><code>{
      "something": "2016-05-03T15:20:46.873Z"
  }
  </code></pre>
  
  <p>Unfortunately I don't know how to override the default behaviour without rewriting everything or changing code in the library itself.</p>
  
  <p>This is where I think it happens (<a href="https://github.com/ReactiveMongo/Reactivemongo-Play-Json/blob/master/src/main/scala/package.scala#L220" rel="nofollow">source code</a>):</p>
  
  <pre><code>val partialWrites: PartialFunction[BSONValue, JsValue] = {
      case dt: BSONDateTime =&gt; Json.obj("$date" -&gt; dt.value)
  }
  </code></pre>
  
  <p>My version would have to look like this:</p>
  
  <pre><code>val partialWrites: PartialFunction[BSONValue, JsValue] = {
      case dt: BSONDateTime =&gt;
          JsString(Instant.ofEpochMilli(dt.value).toString)
  }
  </code></pre>
  
  <p>Is it possible to override this bit?</p>
  
  <p>I have created an experiment...</p>
  
  <pre><code>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" -&gt; 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"}
      }
  
  }
  </code></pre>
  
  <p>I'd like to note that the BSONDateTime conversion to JsValue should always work when I convert a BSONDocument to JsObject, not only when I manually pick a specific known property. This means the property "something" in my example could have any name and also appear in a sub-document.</p>
  
  <p>BTW: In case you wonder, I generally work with BSON collections in my Play project, but I don't think it makes a difference in this case anyway.</p>
  
  <p><strong>Edit</strong></p>
  
  <p>I've tried providing a <code>Writes[BSONDateTime]</code>, but unfortunately it's not being used and I still get the same result as before. Code:</p>
  
  <pre><code>import java.time.Instant
  import play.api.libs.json._
  import reactivemongo.bson.{BSONDocument, BSONDateTime}
  
  object MyImplicits {
      implicit val dateWrites = Writes[BSONDateTime] (bsonDate =&gt;
          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" -&gt; 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}}
      }
  }
  </code></pre>