Heads up, we’ve moved! If you’d like to continue keeping up with the latest technical content from Square please visit us at our new home https://developer.squareup.com/blog

Though it has its wrinkles, I really like JSON. It’s easy to read, pretty fast to parse, and refreshingly simple. Here’s a sample message from GitHub’s exemplar API:

{

"url": "https://api.github.com/repos/square/okio/issues/156",

"id": 91393390,

"number": 156,

"title": "ByteString CharSequence idea",

"state": "open",

"created_at": "2015-06-27T00:49:40.000Z",

"body": "Let's make CharSequence that's backed by bytes.

"

}

Kotlin’s concise immutable data classes make it easy to build a basic model for this JSON.

data class Issue(

val url: String,

val id: Long,

val number: Long,

val title: String,

val state: String,

val created_at: String,

val body: String)

That’s it. No equals() , hashCode() , or toString() boilerplate. We don’t even need a builder! Let’s extend the model to take advantage of Kotlin’s default values and explicit nulls:

data class Issue(

val url: String,

val id: Long,

val number: Long,

val title: String,

val comments: Long = 0L,

val created_at: String,

val closed_at: String?,

val body: String = "")

Default values fill in the gaps when decoding JSON from the network. I like that I can leave them out when creating sample data in my test cases. Explicit nullable types prevent data problems.

Today we’re releasing Moshi 1.5 with powerful Kotlin support via the moshi-kotlin module. Moshi’s type adapters and annotations bind JSON to an idiomatic data model.

data class Issue(

val url: String,

val id: Long,

val number: Long,

val title: String,

val state: IssueState,

val comments: Long = 0L,

@Json(name = "created_at") val createdAt: Date,

@Json(name = "closed_at") val closedAt: Date?,

val body: String = "")

This class uses proper types instead of strings for the issue’s state and timestamps. The @Json annotation maps snake_case names in JSON to camelCase property names in Kotlin.

To set this up I need a Moshi.Builder and a JsonAdapter . I can use Kotlin’s raw strings to embed a sample message right in the code.



{

"url": "

"id": 91393390,

"number": 156,

"title": "ByteString CharSequence idea",

"state": "open",

"created_at": "2015-06-27T00:49:40.000Z"

}

""" val issueJson = """"url": " https://api.github.com/repos/square/okio/issues/156 ","id": 91393390,"number": 156,"title": "ByteString CharSequence idea","state": "open","created_at": "2015-06-27T00:49:40.000Z"""" val moshi = Moshi.Builder()

.add(KotlinJsonAdapterFactory())

.add(Date::class.java, Rfc3339DateJsonAdapter().nullSafe())

.build() val issueAdapter = moshi.adapter(Issue::class.java)

val issue = issueAdapter.fromJson(issueJson)

If you’re using JSON, Moshi and Kotlin help you to build better models with less code. Note that moshi-kotlin uses kotlin-reflect for property binding. That dependency is large by Android standards (1.7 MiB / 11,500 methods). We’re thinking of creative ways to address that!

This post is part of Square’s “Square Open Source ♥s Kotlin” series.