0

Is there a way that I can use the fromJson and toJson methods in my java code? I would want to call it to transform a bson document that I get from mongoldb to a model class that I have in Scala

My Scala object is below,

import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.{DefaultScalaModule, ScalaObjectMapper}

object JsonUtils {

  val mapper = new ObjectMapper() with ScalaObjectMapper

  mapper.registerModule(DefaultScalaModule)
  mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

  def toJson(value: Map[Symbol, Any]): String = {
    toJson(value map { case (k,v) => k.name -> v})
  }

  def toJson(value: Any): String = {
    mapper.writeValueAsString(value)
  }

  def toMap[V](json:String)(implicit m: Manifest[V]) = fromJson[Map[String,V]](json)

  def fromJson[T](json: String)(implicit m : Manifest[T]): T = {
    mapper.readValue[T](json)
  }

  implicit class Marshallable[T](marshallMe: T) {
    def toJson: String = JsonUtils.toJson(marshallMe)
  }

  implicit class Unmarshallable(unMarshallMe: String) {
    def toMap: Map[String,Any] = JsonUtils.toMap(unMarshallMe)
    def fromJson[T]()(implicit m: Manifest[T]): T =  JsonUtils.fromJson[T](unMarshallMe)
  }
}
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
Adi Kish
  • 79
  • 3
  • 9
  • 4
    That Scala code is just a thin wrapper over the Java Jackson library. Why not call that directly? Or alternately, write the code that goes from BSONObject -> Scala case class instance in Scala as well. That method will then have a much simpler signature and be easier to call from Java. – Thilo Oct 07 '20 at 12:14
  • As an experiment I did try what you said on the scala case class conversion and yes it is simpler. I was also looking to reuse more of my scala libraries that were created. Is it by design that scala -> java is more annoying than java to scala? Sorry I might have missed out how much java and scala have evolved. I've mostly been on the kernel side of things – Adi Kish Oct 07 '20 at 19:51
  • 2
    @AdiKish Hardly Java and Scala were evolving trying to make interop Scala -> Java more annoying than vice versa. Just Scala has more features than Java so in the case of Java -> Scala interop you have better chances that those features are naturally expressible than vice versa. – Dmytro Mitin Oct 07 '20 at 22:13

1 Answers1

1

In Java code you have to resolve Scala implicits manually.

Try to call fromJson like

JsonUtils.fromJson("a", scala.reflect.Manifest.classType(LocalUser.class));

or

JsonUtils$.MODULE$.fromJson("a", scala.reflect.Manifest$.MODULE$.classType(LocalUser.class));

Based on Calling a Scala from Java Play Framework which takes a ClassTag

Regarding toJson I can't see problems. Although if you call overloaded version of toJson with Map argument, maybe you'll have to convert between scala.Predef.Map aka scala.collection.immutable.Map and java.util.Map

Convert Java Map to Scala Map

How can I convert Scala Map to Java Map with scala.Float to java.Float k/v conversion

By the way, Manifest is deprecated in favor of ClassTag/TypeTag

https://docs.scala-lang.org/overviews/reflection/typetags-manifests.html

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66