Reputation: 3522
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
Upvotes: 0
Views: 2629
Reputation: 1319
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 .
Upvotes: 2