Skip to main content

Deserialize JSON to Scala Class

There are quite a few libraries that allow us to convert a JSON String into a proper Scala Class (process called deserialization).

Some of the most common are Circe (based on Cats), play-json, Spray Json… However, most of them depend on other heavy libraries. That’s why I found upickle, by Li Haoyi, one of the simplest to use when working on a Spark environment, as it doesn't conflict with anything else.

You can add it into your POM / sbt with the following coordinates:

com.lihaoyi:upickle_2.12:2.0.0

Deserialising a simple json

Having the following json string:

{"attribute1": "Test String", "attribute2": 2}

We need a class that matches that structure:

case class Foo(attribute1: String, attribute2: Int)

And we just need to create an implicit to convert the string to the class:

import upickle.default.{read, reader}

implicit val rw = reader[ujson.Obj].map[Foo] (json => Foo(
read[String](json("attribute")),
read[Int] (json("attribute2"))
))

Now we can use the following piece of code to covert the string into an object of our class:

val jsonString: String = """{"attribute1": "Test String", "attribute2": 2}"""
val foo: Foo = upickle.default.read[Foo](jsonString)

println(foo)

-----
> Foo(Test String, 2)

Working with optional fields

We can also deal with optional fields in a similar way. We only need to write the right implicit that will deal with that situation:

import upickle.default.{read, reader}

case class Foo(attribute1: String, attribute2: Int)

implicit val rw = reader[ujson.Obj].map[Foo] (json => Foo(
read[String](json("attribute")),
if(json.obj.contains("attribute2")) {read[String](json("attribute2")) } else null,
))


val jsonString: String = """{"attribute1": "Test String", "attribute2": 2}"""
val foo: Foo = upickle.default.read[Foo](jsonString)
println(foo)

---
> Foo(Test String, 2)
---

val jsonString2: String = """{"attribute1": "Test String 2"}"""
val foo2: Foo = upickle.default.read[Foo](jsonString2)
println(foo2)

---
> Foo(Test String 2, null)
---