0
0
Android Kotlinmobile~20 mins

JSON parsing with Gson/Moshi in Android Kotlin - Mini App: Build & Ship

Choose your learning style9 modes available
Build: User List Screen
This screen fetches a JSON string of users and shows their names and emails in a list.
Target UI
-------------------------
| User List             |
-------------------------
| • John Doe           |
|   john@example.com   |
| • Jane Smith         |
|   jane@example.com   |
-------------------------
Parse a JSON string containing a list of users with 'name' and 'email' fields.
Use Gson or Moshi library for JSON parsing.
Display the users in a vertical scrollable list.
Each list item shows the user's name in bold and email below it.
Show a loading indicator while parsing.
Handle parsing errors gracefully by showing an error message.
Starter Code
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp

class UserListActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      UserListScreen()
    }
  }
}

@Composable
fun UserListScreen() {
  // TODO: Add state for loading, error, and user list
  // TODO: Parse JSON string using Gson or Moshi
  // TODO: Show loading indicator while parsing
  // TODO: Show error message if parsing fails
  // TODO: Show list of users when parsing succeeds
}
Task 1
Task 2
Task 3
Task 4
Task 5
Task 6
Task 7
Solution
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

class UserListActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      UserListScreen()
    }
  }
}

data class User(val name: String, val email: String)

@Composable
fun UserListScreen() {
  val jsonString = """[
    {\"name\": \"John Doe\", \"email\": \"john@example.com\"},
    {\"name\": \"Jane Smith\", \"email\": \"jane@example.com\"}
  ]"""

  var users by remember { mutableStateOf<List<User>?>(null) }
  var isLoading by remember { mutableStateOf(true) }
  var errorMessage by remember { mutableStateOf<String?>(null) }

  LaunchedEffect(Unit) {
    try {
      val listType = object : TypeToken<List<User>>() {}.type
      users = Gson().fromJson(jsonString, listType)
    } catch (e: Exception) {
      errorMessage = "Failed to parse JSON"
    } finally {
      isLoading = false
    }
  }

  Scaffold(
    topBar = {
      TopAppBar(title = { Text("User List") })
    }
  ) { paddingValues ->
    Box(modifier = Modifier
      .fillMaxSize()
      .padding(paddingValues)) {
      when {
        isLoading -> {
          CircularProgressIndicator(modifier = Modifier.align(androidx.compose.ui.Alignment.Center))
        }
        errorMessage != null -> {
          Text(
            text = errorMessage ?: "",
            color = MaterialTheme.colorScheme.error,
            modifier = Modifier.align(androidx.compose.ui.Alignment.Center)
          )
        }
        users != null -> {
          LazyColumn(modifier = Modifier.fillMaxSize()) {
            items(users!!) { user ->
              Column(modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp)) {
                Text(text = user.name, fontWeight = FontWeight.Bold)
                Text(text = user.email)
              }
              Divider()
            }
          }
        }
      }
    }
  }
}

This solution uses the Gson library to parse a JSON string into a list of User data objects. We define a User data class with name and email fields matching the JSON keys.

In the UserListScreen composable, we keep track of three states: isLoading to show a loading spinner, errorMessage to show an error if parsing fails, and users to hold the parsed list.

We use LaunchedEffect to parse the JSON once when the screen loads. If parsing succeeds, we update users. If it fails, we set an error message.

The UI shows a top app bar with the title. Then it shows a loading spinner while parsing, an error message if parsing fails, or a scrollable list of users if parsing succeeds. Each user item shows the name in bold and the email below.

This approach cleanly separates loading, error, and success states and uses Compose best practices for state and UI updates.

Final Result
Completed Screen
-------------------------
| User List             |
-------------------------
| • John Doe           |
|   john@example.com   |
|-----------------------
| • Jane Smith         |
|   jane@example.com   |
-------------------------
When the screen opens, a loading spinner shows briefly.
Then the list of users appears with their names and emails.
If JSON parsing fails, an error message appears instead.
Stretch Goal
Add a Refresh button in the top app bar to re-parse the JSON and update the list.
💡 Hint
Use a Button or IconButton in the TopAppBar and trigger the parsing logic again on click.