Android Networking: Fundamentals

Sep 6 2022 · Kotlin 1.6, Android 12, Android Studio Chipmunk | 2021.2.1 Patch 1

Part 1: Learn About HTTP & Threading

07. Parse JSON Data

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 06. Challenge: Use HttpUrlConnection Next episode: 08. Challenge: Request & Parse Data

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 07. Parse JSON Data

The student materials have been reviewed and are updated as of July 2022.

Transcript: 07. Parse JSON Data

After practicting parsing the data manually, it’s time to see how you can do it automatically, using a library called GSON.

GSON is a library used to serialize and deserialize objects from JSON to Kotlin or Java objects, and to JSON from Kotlin or Java objects. It can do this even with generics & deep nested object structures. Let’s see how it works!

To begin using GSON, first open up app-module’s build.gradle file. Now add the following dependency:

implementation 'com.google.code.gson:gson:2.8.6'

Sync the project, and you can access the dependency! Now, just like with the previous calls, you need to add the network status checker, and the necessary checks and threading to the NotesFragment. Open up NotesFragment.kt, and add the following code:

private val networkStatusChecker by lazy {
  NetworkStatusChecker(activity?.getSystemService(ConnectivityManager::class.java))
}
networkStatusChecker.performIfConnectedToInternet {
  activity?.runOnUiThread {
    ...
  }
}

Just like before, open the RemoteApi.kt. First add the following object, at the top of the class:

private val gson = Gson()

You only need to create Gson once, and you can reuse it as many times as you want. Head over to the getTasks, and copy the basic structure as with the other requests. Make sure to change the REST method to GET:

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "GET"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doInput = true

  connection.disconnect()
}).start()

Notice the combination of the endpoint path, and the requestMethod. You’re using the GET call, as you’ll be fetching data from an endpoint just for notes. Also notice the authorization header which is used to authenticate with the server. For this request you don’t need to send any data, you can just receive it from the API:

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "GET"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doInput = true

  try {
    val reader = InputStreamReader(connection.inputStream)

    reader.use { input ->
      val response = StringBuilder()
      val bufferedReader = BufferedReader(input)

      bufferedReader.useLines { lines ->
        lines.forEach {
          response.append(it.trim())
        }
      }
    }
  } catch (error: Throwable) {

  }

  connection.disconnect()
}).start()

Just like before, you’re consuming all the lines of the response text. Finally, add the following code, to parse the data, and send it to the UI

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "GET"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doInput = true

  try {
    val reader = InputStreamReader(connection.inputStream)

    reader.use { input ->
      val response = StringBuilder()
      val bufferedReader = BufferedReader(input)

      bufferedReader.useLines { lines ->
        lines.forEach {
          response.append(it.trim())
        }
      }

      val tasksResponse = gson.fromJson(response.toString(), GetTasksResponse::class.java)
      onTasksReceived(tasksResponse.notes, null)
    }
  } catch (error: Throwable) {
    onTasksReceived(emptyList(), error)
  }

  connection.disconnect()
}).start()

The Gson object has multiple methods, for parsing from JSON, and serializing to JSON. In this case, you’re saying you want to parse the response, as a String, into a GetTasksResponse.

It will try to parse the data, and translate keys from the JSON String, to the properties within the class. So a “notes” key in JSON, will translate to a “notes” property in the class. And that’s it! Run the project, and you should see notes from the server show up in your app! :]

Because Gson is so convenient, you can replace the following code in the addTask, login and register calls, to match the getTasks call:

val request = gson.toJson(addTaskRequest)
...
val body = gson.toJson(userDataRequest) // login & register

val task = gson.fromJson(response.toString(), Task::class.java)

You could also change the other response parsing, but since they are simple, you can leave them as is. Run the project once again, and things should be working as before! :]