So here are the answers to the
last post.
Exercise 1: Json Manipulation
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonParser
fun main() {
val usersJson = """[
| {
| "id": "543",
| "username": "john123",
| "firstName": "John",
| "lastName": "Smith",
| "email": "john@smith.com"
| }, {
| "id": "438",
| "username": "janedoe5",
| "firstName": "Jane",
| "lastName": "Doe",
| "email": "jane.doe@gmail.com"
| }
|]""".trimMargin()
val booksJson = """[
| {"id": "1", "title": "Kotlin in Action"},
| {"id": "2", "title": "Kotlin in Action"},
| {"id": "3", "title": "Learning RxJava"},
| {"id": "4", "title": "Refactoring"},
| {"id": "5", "title": "Grokking Algorithms"},
| {"id": "6", "title": "Code Complete"}
|]""".trimMargin()
val checkoutsJson = """[
| {"userId": "543", "bookId": "1"},
| {"userId": "543", "bookId": "5"},
| {"userId": "438", "bookId": "2"},
| {"userId": "438", "bookId": "3"}
|]""".trimMargin()
val parser = JsonParser()
val users = parser.parse(usersJson).asJsonArray
val books = parser.parse(booksJson).asJsonArray
val checkouts = parser.parse(checkoutsJson).asJsonArray
val userCheckouts = users.map { it.asJsonObject }
.flatMap { user -> checkouts.map { it.asJsonObject }
.filter { checkout -> user["id"] == checkout["userId"] }
.map { checkout -> JsonObject().apply {
addProperty("firstName", user["firstName"].asString)
addProperty("lastName", user["lastName"].asString)
addProperty("bookId", checkout["bookId"].asString)
} }
}
.flatMap { userCheckout -> books.map { it.asJsonObject }
.filter { book -> userCheckout["bookId"] == book["id"] }
.map { book -> userCheckout.deepCopy().apply {
addProperty("title", book["title"].asString)
remove("bookId")
} }
}
.fold(JsonArray()) { array, obj -> array.apply { add(obj) }}
println(userCheckouts)
}
Now honestly the java code wasn't very clean and readable to start with, so if we wanted to clean it up a little we could do the following:
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import com.google.gson.JsonParser
fun main() {
val usersJson = """[
| {
| "id": "543",
| "username": "john123",
| "firstName": "John",
| "lastName": "Smith",
| "email": "john@smith.com"
| }, {
| "id": "438",
| "username": "janedoe5",
| "firstName": "Jane",
| "lastName": "Doe",
| "email": "jane.doe@gmail.com"
| }
|]""".trimMargin()
val booksJson = """[
| {"id": "1", "title": "Kotlin in Action"},
| {"id": "2", "title": "Kotlin in Action"},
| {"id": "3", "title": "Learning RxJava"},
| {"id": "4", "title": "Refactoring"},
| {"id": "5", "title": "Grokking Algorithms"},
| {"id": "6", "title": "Code Complete"}
|]""".trimMargin()
val checkoutsJson = """[
| {"userId": "543", "bookId": "1"},
| {"userId": "543", "bookId": "5"},
| {"userId": "438", "bookId": "2"},
| {"userId": "438", "bookId": "3"}
|]""".trimMargin()
val parser = JsonParser()
val users = parser.parse(usersJson).asJsonArray
val books = parser.parse(booksJson).asJsonArray
val checkouts = parser.parse(checkoutsJson).asJsonArray
val userCheckouts = users.map { it.asJsonObject }
.flatMap { user -> findUserCheckouts(user, checkouts)
.map { checkout -> buildUserCheckout(user, checkout) }
}
.flatMap { userCheckout -> findCheckoutBooks(userCheckout, books)
.map { book -> swapBookIdForTitleOnUserCheckout(userCheckout, book) }
}
.toJsonArray()
println(userCheckouts)
}
private fun findUserCheckouts(
user: JsonObject,
checkouts: JsonArray
): List =
checkouts.map { it.asJsonObject }
.filter { checkout -> user["id"] == checkout["userId"] }
private fun buildUserCheckout(
user: JsonObject,
checkout: JsonObject
): JsonObject =
JsonObject().apply {
addProperty("firstName", user["firstName"].asString)
addProperty("lastName", user["lastName"].asString)
addProperty("bookId", checkout["bookId"].asString)
}
private fun findCheckoutBooks(
userCheckout: JsonObject,
books: JsonArray
): List =
books.map { it.asJsonObject }
.filter { book -> userCheckout["bookId"] == book["id"] }
private fun swapBookIdForTitleOnUserCheckout(
userCheckout: JsonObject,
book: JsonObject
): JsonObject =
userCheckout.deepCopy().apply {
addProperty("title", book["title"].asString)
}
private fun List<JsonObject>.toJsonArray(): JsonArray =
fold(JsonArray()) { array, obj -> array.apply { add(obj) }}