简体   繁体   中英

Serialize Scala case classes and deserialize them in Java

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

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);

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM