4

I have a problem when trying to serialize sequences of AnyVal using json4s in scala.

Here is a test using FunSuite that reproduces the problem:

  import org.json4s._
  import org.json4s.jackson.JsonMethods._
  import org.json4s.jackson.Serialization._
  import org.scalatest.{FunSuite, Matchers}

  case class MyId(id: String) extends AnyVal

  case class MyModel(ids: Seq[MyId])

  class AnyValTest extends FunSuite with Matchers {

    test("should serialize correctly") {

      implicit val formats = DefaultFormats

      val model = MyModel(Seq(MyId("1"), MyId("2")))
      val text = write(model)

      parse(text).extract[MyModel] shouldBe model
    }
  }

The test fails when trying to extract MyModel from the JValue because it can not find a suitable value for the ids field.

I notice that it AnyVal are working fine when used directly though with something like:

case class AnotherModel(id: MyId)

Then I am able to serialise and deserialise correctly.

Alexandre
  • 316
  • 2
  • 7
  • does it `case class MyId(id: String) extends AnyVal` have any sence in your opinion? If you want to extend some behaviour, maybe it's better to use *Traits*, don't you think so? – ilyakhov Oct 05 '15 at 15:06

1 Answers1

1

I know this question is one year old but I ran into the same issue. Writing what I did in case it helps someone else. You will need a custom serializer.

case class Id(asString: String) extends AnyVal

class NotificationSerializer extends CustomSerializer[Id](format ⇒ (
  {case JString(s) => Id(s)},
  {case Id(s) => JString(s)}))

Without above serialization, your JSON will look something like

{"ids":[[{"asString":"testId1"},{"asString":"testId2"}]]}

I am not entirely sure why AnyVal case class serialization works fine when it is a part of another case class but not standalone. My best guess is that the behavior is due to the allocation behavior of JVM for array containing value classes. See http://docs.scala-lang.org/overviews/core/value-classes.html for 'when allocation is necessary' section.

Sujeet Sinha
  • 2,417
  • 2
  • 18
  • 27
richak
  • 49
  • 3