I have a problem serializing a Model class to JSON.
Thanks in advance!
ContextI have a model entity implemented as a case class with
Gremlin Scala for the graph database
OrientDb.
Orientdb uses as record id the Java class
ORecordId wich is implemented as an Option[string] with @id annotation as Gremlin Scala readme states to do:
case class Account(@id id: Option[String], username: String, password: String)
A controller implemented with akka-http is charged to provide such entity in a Json format using spray.json.
def createAccount(username: String, password: String): Either[String, Account] = {
Account.createAccount(username, password) match {
case Some(account) => Right(account)
case None => Left("account not created or already exists")
}
}
and the route is:
(post & entity(as[AccountWithoutId])) {
accountCreateRequest => complete {
createAccount(accountCreateRequest.username, accountCreateRequest.password) match {
case Right(success) => ToResponseMarshallable(success)
case Left(failure) => BadRequest -> failure
}
}
}
ProblemWhen trying to serialize such case class to Json i get the following error:
ms-accounts java.lang.ClassCastException: com.orientechnologies.orient.core.id.ORecordId cannot be cast to java.lang.String
ms-accounts at spray.json.BasicFormats$StringJsonFormat$.write(BasicFormats.scala:119)
ms-accounts at spray.json.PimpedAny.toJson(package.scala:39)
ms-accounts at spray.json.StandardFormats$OptionFormat.write(StandardFormats.scala:34)
ms-accounts at spray.json.StandardFormats$OptionFormat.write(StandardFormats.scala:32)
ms-accounts at spray.json.ProductFormats$class.productElement2Field(ProductFormats.scala:46)
ms-accounts at AkkaHttpMicroservice$.productElement2Field(AkkaHttpMicroservice.scala:110)
ms-accounts at spray.json.ProductFormatsInstances$$anon$3.write(ProductFormatsInstances.scala:72)
ms-accounts at spray.json.ProductFormatsInstances$$anon$3.write(ProductFormatsInstances.scala:68)
ms-accounts at spray.json.PimpedAny.toJson(package.scala:39)
ms-accounts at controller.AccountService$$anonfun$3$$anonfun$apply$1$$anonfun$apply$2$$anonfun$apply$3.apply(AccountController.scala:67)
ms-accounts at controller.AccountService$$anonfun$3$$anonfun$apply$1$$anonfun$apply$2$$anonfun$apply$3.apply(AccountController.scala:66)
ms-accounts at akka.http.scaladsl.server.directives.RouteDirectives$$anonfun$complete$1.apply(RouteDirectives.scala:59)
ms-accounts at akka.http.scaladsl.server.directives.RouteDirectives$$anonfun$complete$1.apply(RouteDirectives.scala:59)
ms-accounts at akka.http.scaladsl.server.StandardRoute$$anon$1.apply(StandardRoute.scala:19)
ms-accounts at akka.http.scaladsl.server.StandardRoute$$anon$1.apply(StandardRoute.scala:19)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:52)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:52)
ms-accounts at akka.http.scaladsl.server.directives.FutureDirectives$$anonfun$onComplete$1$$anonfun$apply$1$$anonfun$apply$2.apply(FutureDirectives.scala:31)
ms-accounts at akka.http.scaladsl.server.directives.FutureDirectives$$anonfun$onComplete$1$$anonfun$apply$1$$anonfun$apply$2.apply(FutureDirectives.scala:31)
ms-accounts at akka.http.scaladsl.util.FastFuture$$anonfun$transformWith$extension0$1.apply(FastFuture.scala:37)
ms-accounts at akka.http.scaladsl.util.FastFuture$$anonfun$transformWith$extension0$1.apply(FastFuture.scala:37)
ms-accounts at akka.http.scaladsl.util.FastFuture$.akka$http$scaladsl$util$FastFuture$$strictTransform$1(FastFuture.scala:41)
ms-accounts at akka.http.scaladsl.util.FastFuture$.transformWith$extension1(FastFuture.scala:45)
ms-accounts at akka.http.scaladsl.util.FastFuture$.transformWith$extension0(FastFuture.scala:37)
ms-accounts at akka.http.scaladsl.server.directives.FutureDirectives$$anonfun$onComplete$1$$anonfun$apply$1.apply(FutureDirectives.scala:31)
ms-accounts at akka.http.scaladsl.server.directives.FutureDirectives$$anonfun$onComplete$1$$anonfun$apply$1.apply(FutureDirectives.scala:29)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:52)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:52)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:34)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:34)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:44)
ms-accounts at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:42)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:34)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRequestContext$1$$anonfun$apply$1.apply(BasicDirectives.scala:34)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1$$anonfun$apply$1.apply(RouteConcatenation.scala:47)
ms-accounts at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1$$anonfun$apply$1.apply(RouteConcatenation.scala:44)
ms-accounts at akka.http.scaladsl.util.FastFuture$.akka$http$scaladsl$util$FastFuture$$strictTransform$1(FastFuture.scala:41)
ms-accounts at akka.http.scaladsl.util.FastFuture$.transformWith$extension1(FastFuture.scala:45)
ms-accounts at akka.http.scaladsl.util.FastFuture$.flatMap$extension(FastFuture.scala:26)
ms-accounts at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:44)
ms-accounts at akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1.apply(RouteConcatenation.scala:42)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:52)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResult$1$$anonfun$apply$3.apply(BasicDirectives.scala:52)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResultWith$1$$anonfun$apply$4.apply(BasicDirectives.scala:58)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$mapRouteResultWith$1$$anonfun$apply$4.apply(BasicDirectives.scala:58)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.BasicDirectives$$anonfun$textract$1$$anonfun$apply$5.apply(BasicDirectives.scala:145)
ms-accounts at akka.http.scaladsl.server.directives.ExecutionDirectives$$anonfun$handleExceptions$1$$anonfun$apply$1.apply(ExecutionDirectives.scala:33)
ms-accounts at akka.http.scaladsl.server.directives.ExecutionDirectives$$anonfun$handleExceptions$1$$anonfun$apply$1.apply(ExecutionDirectives.scala:29)
ms-accounts at akka.http.scaladsl.server.Route$$anonfun$asyncHandler$1.apply(Route.scala:70)
ms-accounts at akka.http.scaladsl.server.Route$$anonfun$asyncHandler$1.apply(Route.scala:69)
ms-accounts at akka.stream.impl.fusing.MapAsync$$anon$8.onPush(Ops.scala:761)
ms-accounts at akka.stream.impl.fusing.GraphInterpreter.processElement$1(GraphInterpreter.scala:587)
ms-accounts at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:598)
ms-accounts at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:539)
ms-accounts at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:469)
ms-accounts at akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:421)
ms-accounts at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:593)
ms-accounts at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:604)
ms-accounts at akka.actor.Actor$class.aroundReceive(Actor.scala:482)
ms-accounts at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:519)
ms-accounts at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
ms-accounts at akka.actor.ActorCell.invoke(ActorCell.scala:495)
ms-accounts at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
ms-accounts at akka.dispatch.Mailbox.run(Mailbox.scala:224)
ms-accounts at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
ms-accounts at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
ms-accounts at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
ms-accounts at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
ms-accounts at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
I looked in
ORecordId class implementation and a toString method exists.
Tried solutionI tried implementing a custom JsonFormat (as described in
Providing JsonFormats for other Types and
here):
trait AccountProtocols extends DefaultJsonProtocol {
implicit val accountWithoutIdFormat = jsonFormat2(AccountWithoutId.apply)
implicit val accountFormat = jsonFormat3(AccountWithStringId.apply)
implicit object JsonORecordIdFormatClass extends JsonFormat[ORecordId] {
def write(obj: ORecordId) = JsString(obj.toString)
def read(json: JsValue) : ORecordId = json match {
case JsString(langString) => new ORecordId(langString)
case _ => throw new DeserializationException("ORecordId expected")
}
}
}
but I get the exact same problem.