jackson-module-scala icon indicating copy to clipboard operation
jackson-module-scala copied to clipboard

Cannot serialize option of anyval in a collection

Open devshorts opened this issue 9 years ago • 4 comments

I have a sample test here:

  "Anyvals" should "serialize json" in {
    val groups = (0 until 10).map(_ =>
      AnyHolder(
        Some(TestAny("data"))
      ))

    val objectMapper = new ObjectMapper().registerModule(DefaultScalaModule)
    println(objectMapper.writeValueAsString(data))
  }
}

case class AnyHolder(
  testAny: Option[TestAny]
)

case class TestAny(data: String) extends AnyVal

This fails with

tests.TestAny cannot be cast to java.lang.String (through reference chain: scala.collection.convert.IterableWrapper[0]->tests.AnyHolder["testAny"])
com.fasterxml.jackson.databind.JsonMappingException: tests.TestAny cannot be cast to java.lang.String (through reference chain: scala.collection.convert.IterableWrapper[0]->tests.AnyHolder["testAny"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:378)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:338)
    at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:342)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:686)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:149)
    at com.fasterxml.jackson.module.scala.ser.IterableSerializer$class.serializeContents(IterableSerializerModule.scala:28)
    at com.fasterxml.jackson.module.scala.ser.UnresolvedIterableSerializer.serializeContents(IterableSerializerModule.scala:56)

Using jackson-core 2.7.4, jackson-databind 2.7.4, jackson-scala-module 2.7.4

Are there any workarounds to get this to work?

devshorts avatar Aug 22 '16 17:08 devshorts

As a temporary workaround I disabled anyval support in my application and to get the json to be over the wire the same I added the @(JsonValue @getter) annotation to the wrapped field.

devshorts avatar Aug 22 '16 17:08 devshorts

Having the same issue, is there is work around?

Assarin avatar May 30 '19 20:05 Assarin

@Assarin I in general moved off of anyval support for all my scala stuff. It was too problematic. I instead created this https://github.com/paradoxical-io/scala-global/tree/master/jackson/src/main/scala/io/paradoxical/jackson which is custom jackson module that knows how to serialize and deserialize tagged types using a trait:

https://github.com/paradoxical-io/scala-global/blob/master/global/src/main/scala/io/paradoxical/global/tiny/Tiny.scala

which i use like this:

https://github.com/paradoxical-io/scala-global/blob/master/jackson/src/test/scala/io/paradoxical/jackson/TinyTests.scala

I found this to be easier to give me the NewType support but still play nice with serialization/swagger/reflection/etc.

These jars are available on maven central if you are interested

akropp-stripe avatar May 30 '19 20:05 akropp-stripe

@Assarin yet another option is to use jsoniter-scala - it has support of AnyVals with any combination of Scala collection and other types. Also it is much safe and efficient than other options.

plokhotnyuk avatar May 30 '19 20:05 plokhotnyuk