Christian H. Kuhn
Christian H. Kuhn

Reputation: 353

uPickle ReadWriter for joda DateTime fails

For a project, i need JSON representation for a org.joda.time.DateTime. For JSON, i use uPickle. As there is no implicit ReaderWriter[DateTime], i have to write it myself. After googleing around, i came up with the following code:

import com.github.nscala_time.time.Imports.DateTime
import org.joda.time.format.ISODateTimeFormat
import upickle.default._

object DateTimeRW:
  val fmt = ISODateTimeFormat.dateTime()
  given ReadWriter[DateTime] = readwriter[ujson.Value].bimap[DateTime](
    dt => fmt.print(dt),
    dtstr => fmt.parseDateTime(dtstr.str)
  )

val dt = DateTime.now()
val jsonDateString = write(dt)
val dt2: DateTime = read(dt.toString)

It fails. I do not even understand the errors:

missing argument for parameter evidence$5 of method write in trait Api: (implicit evidence$5: upickle.default.Writer[org.joda.time.DateTime]): String

missing argument for parameter evidence$3 of method read in trait Api: (implicit evidence$3: upickle.default.Reader[T]): T

It seems that my implementation is wrong, but i cannot detect any syntactical error like a missing argument. Google finds NO answers for the error descriptions. Can someone help?

Upvotes: 1

Views: 94

Answers (1)

boggy
boggy

Reputation: 4027

This compiles and works:

import com.github.nscala_time.time.Imports.DateTime
import org.joda.time.format.ISODateTimeFormat
import upickle.default._
import upickle.default.ReadWriter.join

object DateTimeRW:
    val fmt = ISODateTimeFormat.dateTime()
    given ReadWriter[DateTime] = readwriter[ujson.Value].bimap[DateTime](
        x => fmt.print(x),
        dtstr => fmt.parseDateTime(dtstr.str)
    )
import DateTimeRW.given_ReadWriter_DateTime

def main(args: Array[String]): Unit = {
  val dt = DateTime.now()
  val jsonDateString = write(dt)
  println(jsonDateString)
  val dt2: DateTime = read(jsonDateString)
  println(dt2)
}

sbt:

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "3.4.2"

lazy val root = (project in file("."))
  .settings(
    name := "ScalaStuff"
  )

libraryDependencies += "com.lihaoyi" %% "upickle" % "4.0.0-RC1"
libraryDependencies += "joda-time" % "joda-time" % "2.12.7"
libraryDependencies += "com.github.nscala-time" %% "nscala-time" % "2.32.0"

This one compiles and works as well (it is based on this example):

import com.github.nscala_time.time.Imports.DateTime
import org.joda.time.format.ISODateTimeFormat
import upickle.default._
import upickle.default.ReadWriter.join

//object DateTimeRW:
//    val fmt = ISODateTimeFormat.dateTime()
//    given ReadWriter[DateTime] = readwriter[ujson.Value].bimap[DateTime](
//        x => fmt.print(x),
//        dtstr => fmt.parseDateTime(dtstr.str)
//    )
//import DateTimeRW.given_ReadWriter_DateTime

object DateTimeRw2:
    val fmt = ISODateTimeFormat.dateTime()
    implicit val rw: ReadWriter[DateTime] = upickle.default.readwriter[String].bimap[DateTime](
         x => fmt.print(x),
         dtAsStr => DateTime.parse(dtAsStr, fmt)
    )
import DateTimeRw2.*

def main(args: Array[String]): Unit = {
  val dt = DateTime.now()
  val jsonDateString = write(dt)
  println(jsonDateString)
  val dt2: DateTime = read(jsonDateString)
  println(dt2)
}

Note that I didn't have to be so explicit in my import as I've been in the other case.

Unfortunately, I have to admit, I don't know enough about the compiler to explain you why exactly in the other case you need to be explicit in importing the given (just import DateTimeRw.* doesn't do it), and why when using the implicit val, it seems to work. I probably need to brush up my knowledge on how the compiler resolves these.

You can assign your own name if you don't like the compiler default:

object DateTimeRW:
    val fmt = ISODateTimeFormat.dateTime()
    given rw: ReadWriter[DateTime] = readwriter[ujson.Value].bimap[DateTime](
        x => fmt.print(x),
        dtstr => fmt.parseDateTime(dtstr.str)
    )
import DateTimeRW.rw

Note:

read(dt.toString)

This is incorrect. You want: read(jsonDateString).

Upvotes: 1

Related Questions