0
votes

I am trying to convert a case class to Json String using Json4s. I am getting the exception

MappingException: Can't find ScalaSig for class java.lang.Object

This is happening if I am extending my case class with another trait only.

My code is as below:

trait Integration {
  val thirdpartyId: Option[Long]
}

trait HrIntegration extends Integration {
  override val thirdpartyId: Option[Long] = getValue
  def getValue = {
    Some(100L)
  }
}

case class Employee(id: Long, name: String, age: Long) extends HrIntegration


object Test extends App {
  import org.json4s.Extraction
  import org.json4s.jackson.JsonMethods._
  import org.json4s.DefaultFormats
  implicit lazy val serializerFormats = DefaultFormats
  val emp = Employee(1, "Yadu", 27)
  val jValue = Extraction.decompose(emp)
  val jsonString = compact(jValue)
  println(jsonString)
}

If I convert Option[Long] to Option[BigInt], it works fine. The same issue is with Option[Double] as well.

When I went through the stacktrace and subsequent googling, I found that the issue is with the reflection, due to scala version mismatch. So I added scala reflect library dependency as below:

"org.scala-lang" % "scala-reflect" % "2.11.7",
"org.scala-lang" % "scalap" % "2.11.7"

But even after that, I am getting the same error. I have fixed the issue for now by using BigInt and BigDecimal instead of Long and Double.

Can someone please help me to understand the issue and how I can fix it by using Long and Double itself.

Json4s Version : 3.2.11
Scala Version : 2.11.7
1
It would probably help if you showed us the actual json serialization in Extraction.decompose(emp).Peter Neyens
What do u mean by actual json serialization? I am invoking the decompose() method of org.json4s.Extraction, which takes Any.Yadu Krishnan
What result of Extraction.decompose(emp) do you expect?ilyakhov

1 Answers

2
votes

Yadu, you should add class for custom serialization. It could looks like

class EmployeeSerializer extends CustomSerializer[Employee](format => (
  {
    case JObject(JField("id", JInt(i)) :: JField("name", JString(n)) :: JField("age", JInt(a)) ::Nil) =>
      new Employee(i.longValue, n, a.longValue)
  },
  {
    case x @ Employee(i: Long, n: String, a: Long) =>
      JObject(JField("id", JInt(BigInt(i))) ::
        JField("name",   JString(n)) ::
        JField("age",   JInt(BigInt(a))) :: Nil)
  }
  ))

and also you should modify formats:

implicit val formats = DefaultFormats + new EmployeeSerializer

So, the result is:

import org.json4s._

trait Integration {
  val thirdpartyId: Option[Long]
}
trait HrIntegration extends Integration {
  override val thirdpartyId: Option[Long] = getValue
  def getValue = {
    Some(100L)
  }
}
case class Employee(id: Long, name: String, age: Long) extends HrIntegration

class EmployeeSerializer extends CustomSerializer[Employee](format => (
  {
    case JObject(JField("id", JInt(i)) :: JField("name", JString(n)) :: JField("age", JInt(a)) ::Nil) =>
      new Employee(i.longValue, n, a.longValue)
  },
  {
    case x @ Employee(i: Long, n: String, a: Long) =>
      JObject(JField("id", JInt(BigInt(i))) ::
        JField("name",   JString(n)) ::
        JField("age",   JInt(BigInt(a))) :: Nil)
  }
  ))

object Test extends App {
  import org.json4s.Extraction
  import org.json4s.DefaultFormats
  implicit val formats = DefaultFormats + new EmployeeSerializer
  val emp = Employee(1, "Yadu", 27)
  val jValue = Extraction.decompose(emp)
  println(jValue)
}

It returns:

JObject(List((id,JInt(1)), (name,JString(Yadu)), (age,JInt(27))))

You can find additional information on the page of json4s project: https://github.com/json4s/json4s#serializing-non-supported-types .