Intro to Android Development
  • Welcome
  • Syllabus
  • Hack Challenge
  • Resources
    • Lecture Videos
    • Ed Discussion
    • Git & GitHub Help/How-To
    • Setting up Android Studio
    • Starting an Android Studio Project & Making an Emulator
    • Importing, Exporting, & Submitting Your Projects to CMS
  • SP25 Course Material
    • Week 1 | Course Logistics, Kotlin, & Basic UI
      • Relevant Links
      • Demo/Lecture: Eatery Card
      • A0: Eatery Card (Follow-Along)
    • Week 2 | States, Components, LazyColumn
      • Relevant Links
      • Demo: Todo List
      • A2: Shopping List
    • Week 3 | Navigation & Animations
      • Relevant Links
      • Demo: Onboarding
      • A3: Stock Trading (RobbingGood)
    • Week 4 | MVVM and Flows
      • Relevant Links
      • Demo: Eatery Card 2
      • A4: Chat of a Lifetime
    • Week 5 | Dumb Components & UIEvents
      • Relevant Links
      • Demo: Music Player
      • A5: Rate My Vibe
    • Week 6 | Coroutines, Networking, JSON
      • Relevant Links
      • Demo: Retrofit
      • A6: You Should Even Lift, Bro.
  • Bonus Week | Android Job Search
    • Relevant Links
    • Android Technical Interview Question!
  • Textbook
    • 1. Introduction to the Editor and Views
      • 1.1 Introduction to the Editor
      • 1.2 SDK Management
      • 1.3 Kotlin Overview
      • 1.4 Views
      • 1.5 Android Studio Project Demo + Understanding The Editor
    • 2. Jetpack Compose
      • 2.1 Introduction
      • 2.2 Layouts
      • 2.3 Modifiers
      • 2.4 Animations
      • 2.5 Lazy Lists
      • 2.6 Reactive UI
    • 3. Intents and Manifest
      • 3.1 Activities
      • 3.2 Implicit Intents
      • 3.3 Explicit Intents
      • 3.4 Manifest
      • 3.5 Permissions
      • 3.6 Summary
    • 4. Navigation
      • 4.1 Types of Navigation
      • 4.2 Implementation of the Bottom Navigation Bar
    • 5. Data and Persistent Storage
      • 5.1 Singleton Classes
      • 5.2 Shared Preferences
      • 5.3 Rooms
      • 5.4 Entities
      • 5.5 Data Access Objects
      • 5.6 Databases
    • 5.5 Concurrency
      • 5.5.1 Coroutines
      • 5.5.2 Implementation of Coroutines
      • 5.5.3 Coroutines with Networking Calls
    • 6. Networking and 3rd Party libraries
      • 6.1 HTTP Overview
      • 6.2 3rd Party Libraries
      • 6.3 JSON and Moshi
      • 6.4 Retrofit
      • 6.5 Summary
    • 7. MVVM Design Pattern
      • 7.1 Key Idea
      • 7.2 Implementation Ideas
    • 8. Flows
    • 9. The Art and Ontology of Software
    • 10. 🔥 Firebase
      • 10.1 Setting up Firebase
      • 10.2 Authentication
      • 10.3 Analytics
      • 10.4 Messaging
      • 10.5 Firestore
  • Additional Topics
    • Git and GitHub
    • Exporting to APK
  • Archive
    • Archived Native Android Textbook Pages
      • 1. Layouts and More Views
        • 1.1 File Structure and File Types
        • 1.2 Resource Files
        • 1.3 Button and Input Control
        • 1.4 ViewGroups
        • 1.5 Summary + A Note On Chapter 2 Topics
      • 2. RecyclerViews
        • 2.1 RecyclerViews
        • 2.2 RecyclerView Performance
        • 2.3 Implementation of a Recycler View
        • 2.4 Implementation with Input Controls
        • 2.5 Filtering RecyclerViews
        • 2.6 Recyclerview Demo
      • 3. ListViews and Searching
        • 3.1 ListView vs. RecyclerView
        • 3.2 ListView Performance
        • 3.3 Implementation of a ListView
        • 3.4 Searching in a List View
      • 4. Fragments
        • 4.1 What are Fragments?
        • 4.2 Lifecycle of a Fragment
        • 4.3 Integrating a Fragment into an Activity
        • 4.4 Sharing Data Between Fragments
        • 4.5 Fragment Slide Shows
      • 5. OkHttp
      • 6. Activity Lifecycle
      • 7. Implementation of Tab Layout
    • Fall 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 1.5: Beauty of Kotlin
      • Lecture 2 & HW 2: Modifiers, Lazylists and Reactive UI
      • Lecture 3 & HW 3: Animations, Intents and Manifest
      • Lecture 4 & HW 4: Coroutines & Navigation
      • Lecture 5 & HW 5: Persistent Storage, Networking, and JSON Parsing
      • Lecture 6 & HW 6: MVVM, Flows
      • Bonus Lectures & Bonus HW
      • Bonus Lecture: Industry Practice
    • Spring 2024 Course Material
      • Lecture 1 & Exercise 1: Introduction to Android
      • Lecture 4 & HW 4: LazyLists
      • Lecture 6 & HW 6: Networking, Data, and Persistent Storage
    • Spring 2020 Course Material
      • Week 1: Intro to the Editor
      • Week 2: Views and Layouts
      • Week 3: Intent and Manifest
      • Week 4: ListView and RecyclerView
      • Week 5: Fragments
      • Week 6: Networking
    • Spring 2021 Lecture & HW 8: Networking & 3rd Party APIs
    • HackOurCampus Workshop
Powered by GitBook
On this page
  • What is a JSON?
  • Using Moshi
  • Setting up
  • Converting JSON -> Kotlin
  • Converting Kotlin -> JSON
  • Parse JSON Arrays
  • Custom field names with @Json

Was this helpful?

  1. Textbook
  2. 6. Networking and 3rd Party libraries

6.3 JSON and Moshi

Previous6.2 3rd Party LibrariesNext6.4 Retrofit

Last updated 7 months ago

Was this helpful?

What is a JSON?

JSON, or JavaScript Object Notation, is a way of representing data. While its syntax comes from JavaScript, it is still language independent.

When it comes to networking, JSON is typically used in two cases. One is to POST data to a server. The other is a server’s response to the client. Servers may choose to use other formats, like XML, so don’t assume that every server will use JSON (but it is the most common type of format).

There are two main advantages when using JSON with networking. It's very easy for a client to parse the file. Also, it is easily formatted in a way that’s easy for us humans to read.

Above is a sample of JSON data (if you're familiar with python, it looks very similar to a dictionary).

The data consists of pairs of keys and values. There is a colon character separating each key and value. In the example, base is a key, and GBP is the corresponding value. A comma separates each pair.

A value can be a string in double quotes, or a number, or true or false or null, or another object or an array. These structures can be nested (e.g. I can have an array be a list of objects).

Information within curly braces is an object. In the example above, the value for the rates key is another object, containing more pairs.

Above is an example of a JSON array.

See how this starts and ends with square brackets? This indicates that the data is an array. Each object is a separate ‘record’ or element in the array. Each object in the array is also separated by a comma.

For the sake of example, the array is a list of objects but the array can be a list of any of the valid JSON types (you can also have arrays of many different types).

Using Moshi

Setting up

In a language like python, we would need to pip install x and then later import x but in Kotlin we have a much more complicated file structure and system so we do the following (typically):

In the build.gradle we have to add dependencies to "install" the library

Add the following dependencies in your module-level build.gradle file:

// Plugins should be located at the very top of your file
apply plugin: 'kotlin-kapt'

// Alternative if your plugins look like this!
plugins {
   ...
   id 'kotlin-kapt' 
}

...

dependencies {
   implementation("com.squareup.moshi:moshi-kotlin:1.13.0")
   kapt("com.squareup.moshi:moshi-kotlin-codegen:1.13.0")
}

We're gonna be referring to the classes below as we introduce Moshi:

@JsonClass(generateAdapter = true) // Data classes MUST have this line right above
data class BlackjackHand(
  val hidden_card: Card,
  val visible_cards: List<Card>,
  ...
)

@JsonClass(generateAdapter = true)
data class Card(
  val rank: Char,
  val suit: Suit
  ...
)

@Keep
enum class Suit {
  CLUBS, DIAMONDS, HEARTS, SPADES;
}

Moshi gives us JSONs like this that we can read from and write to:

{
  "hidden_card": {
    "rank": "6",
    "suit": "SPADES"
  },
  "visible_cards": [
    {
      "rank": "4",
      "suit": "CLUBS"
    },
    {
      "rank": "A",
      "suit": "HEARTS"
    }
  ]
}

Converting JSON -> Kotlin

If we want to convert JSONs into objects of our Kotlin class, we can do something like what's below:

val json: String = ... // JSON from our response

val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = 
    moshi.adapter<BlackjackHand>(BlackjackHand::class.java)

// fromJson(...) convers the JSON into a BlackjackHand
val blackjackHand: BlackjackHand = jsonAdapter.fromJson(json)

Converting Kotlin -> JSON

If we want to go the other way around:

val blackjackHand = BlackjackHand(
    Card('6', SPADES),
    listOf(Card('4', CLUBS), Card('A', HEARTS))
  )

val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = 
    moshi.adapter<BlackjackHand>(BlackjackHand::class.java)

// JSON that can be used in a POST request body, etc.
val json: String = jsonAdapter.toJson(blackjackHand)

Moshi has built-in support for reading and writing Kotlin's core data types:

  • Primitives (int, float, char...)

  • Arrays, Collections, Lists, Sets, and Maps

  • Strings

  • Enums

Parse JSON Arrays

Say we have a JSON string of this structure:

[
  {
    "rank": "4",
    "suit": "CLUBS"
  },
  {
    "rank": "A",
    "suit": "HEARTS"
  }
]

We can now use Moshi to parse the JSON string into a List<Card>:

val cardArrayJsonResponse: String = ...


// Creates a List<Card> type to adapt from
val type = Types.newParameterizedType(
    List::class.java, //List:class.java must come first!
    Card::class.java
)

val adapter = moshi.adapter<List<Card>>(type)
val cards: List<Card> = adapter.fromJson(cardsJsonResponse)

Custom field names with @Json

Moshi works best when your JSON objects and Java or Kotlin classes have the same structure. But when they don't, Moshi has annotations to customize data binding.

Use @Json to specify how Kotlin properties map to JSON names. This is necessary when the JSON name contains spaces or other characters that aren’t permitted in Kotlin property names. For example, this JSON has a field name containing a space:

{
  "username": "jesse",
  "lucky number": 32
}

We can't have spaces in our Kotlin property names, so we can create a mapping of how Moshi should convert ourselves:

data class Player(
  val username: String
  @Json(name = "lucky number") val luckyNumber: Int

  ...
)

From this you can kind of see how tedious it would be to try and iterate through an array like this to parse the JSON objects (which is where comes into play to make this process easier for us)!

Many times what's returned from networking calls are class objects represented as JSONs, which can be a headache to try and parse manually (and often times isn't as efficient). In comes , which is a handy library also developed by Square used for converting between JSON and Kotlin objects. In tandem they make networking in Android super easy!

Pay special note that the names of our fields in our data class should correspond to what we expect to receive from our response. Check out to see how we can change that!

Moshi
Moshi
this section
Example JSON
JSON Array
The build.gradle we want is the second listed!