# 6.3 JSON and Moshi

## 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.

![Example JSON](/files/7rHCCUpeSUyM6OGL9Aot)

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.

![JSON Array](/files/2ToFmYlh44n1qAQ4wLGe)

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.&#x20;

{% hint style="info" %}
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).
{% endhint %}

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 [Moshi](https://github.com/square/moshi) comes into play to make this process easier for us)!

## Using Moshi

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 [**Moshi**](https://github.com/square/moshi), 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!

### 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

![The build.gradle we want is the second listed!](/files/7AJgXyMU32Bi1OpxOudF)

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

```groovy
// 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:

```kotlin
@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:

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

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[ this section](#custom-field-names-with-json) to see how we can change that!

### Converting JSON -> Kotlin

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

```kotlin
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:

```kotlin
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:

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

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

```kotlin
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:

```json
{
  "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:

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

  ...
)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://android-course.cornellappdev.com/chapters/6.-networking/6.3-json-and-moshi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
