Safe Parsing Kotlin Data-classes with Gson

Dmitry Si
ProAndroidDev
Published in
2 min readAug 28, 2019

--

Kotlin Data Classes are great; they’re concise, they’re null-safe. Gson is great as well; it’s a de-facto standard for JSON parsing on Android for a good reason. But! Data classes parsed via Gson guarantee neither null-safety nor even default values. Or do they?

The Problem

There is an excellent article describing an issue. TL;DR if you have a data class like that

the default values will be ignored, so JSON like {"intValue":2} will produce object {intValue=2,srtValue=null} instead of expected {intValue=2,srtValue="default"}

Good news, there is a way to fix that!

The Solution

Let’s change our data class a little bit.

Notice the subtle difference? This class defines default values for all fields. That’s it! As soon as all the fields have the default values, Gson will respect them when the corresponding fields are missing in JSON (if you don’t need the default values, use nulls).

Why does it work?

The Reason

It really boils down to two features.

1. Kotlin’s Java Overloads.

Compare two classes

the byte-code for them will result with the following Java

Resulting Java code with insignificant parts removed

as soon as all fields have the default values, Kotlin compiler will generate default parameterless constructor in addition to the other overloaded versions it produces.

2. Java’s Unsafe Invocations in Gson

The presence of default constructor is important for Gson. The way it works is roughly the following (see ConstructorConstructor’s code for more details):

  • try to create an object via provided InstanceCreator implementation based on type-token
  • try to invoke the default constructor
  • try to invoke known constructor for maps, sets, queues, etc.
  • use unsafe allocation if nothing helps (more details about unsafe allocation)

That means, if you don’t provide the instance creator and your class doesn’t have the default constructor, the object will be created without the constructor call. Kotlin puts all the null checks and default values assignments to the constructor, so all of them will be skipped.

So if you’re good with Gson and not ready yet to move to a new library that supports Kotlin defaults like Moshi, define all default values in data classes and let Gson do the rest.

Is that it? Well…

The caveat

The solution above works well for JSON with missed fields, but there is one more problem. The nullability defined in Kotlin code may not be respected in JSON, and Gson will not complain about JSON like {"intValue":2,"strValue":null} that contains explicit null. If that kind of situation possible, define all non-primitive fields as nullable to avoid unexpected crashes in production.

Now that’s it. Happy parsing!

--

--

Software developer. Most recently Android Java/Kotlin engineer. Former manager, desktop and embedded software creator. https://github.com/fo2rist/