2

I need to serialize a hierarchy of scala case classes as JSON to store them in a db. I am currently using json4s and it works quite well. However, when deserializing in Java jackson requires me to have an empty constructor for case classes (which doesn't exist).

The other option I tried is to define a deserialization function in my scala library, import it in the Java code and run it at runtime to read a string and build the relative class of the hierarchy. In this way I am able to reconstruct the object in the Java world. Afterwards, I want to return this object: if I return it as an object I am not able to serialize it correctly (jackson uses different logic than json4s); if I use my scala function, I am able to create a string and return it, but for some reasons it gets returned escaped:

"{\"jsonClass\":\"TimeExtremaConfig\",\"name\":\"payment_first_seen_hotel_id_on_agency\"}

Is there a better way to approach this problem? Either finding a way to deserialize case classes and use jackson all over the place or avoiding the escaping in the second option

alexlipa
  • 1,131
  • 2
  • 12
  • 27
  • Are you serializing classes or **objects**? Also: you mean that you have Java code that runs Jackson, to serialize into classes that were compiled from Scala source code? – GhostCat Apr 18 '19 at 14:13

2 Answers2

2

Have you tried using the Jackson Scala Module?

It does a pretty good job of handling instances of case classes within Scala:

case class Parent(name: String, children: List[Child])
case class Child(name: String)

def test(): Unit = {

  val mapper = new ObjectMapper() with ScalaObjectMapper
  mapper.registerModule(DefaultScalaModule)

  val bobString = mapper.writeValueAsString(Parent("Bob", List(Child("Alice"))))
  println(s"String: $bobString")

  val bob = mapper.readValue[Parent](bobString)
  println(s"Object: $bob")
}

Ouputs:

String: {"name":"Bob","children":[{"name":"Alice"}]}
Object: Parent(Bob,List(Child(Alice)))

And you can effectively do the same from the Java side (please excuse the collection interop):

final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new DefaultScalaModule());

final Child alice = new Child("Alice");
final List<Child> children = new ArrayList<>();
children.add(alice);

final String bobString = mapper.writeValueAsString(
  new Parent("Bob", 
    JavaConversions.asScalaBuffer(children).toList()));
System.out.println(bobString);

final Parent bob = mapper.readValue(bobString, Parent.class);
System.out.println(bob);
mforrest
  • 71
  • 3
0

it sounds like you have control over the scala library, how about trying the JsonCreator annotation with the case class? Must we use @JsonProperty in Scala case classes?

While it doesn't look great, it tells jackson to use the parametrized constructor instead of looking for the default constructor.

K_U
  • 15,832
  • 8
  • 26
  • 29