·7 min read
Using JSON in Mobile Development: iOS, Android, and React Native
JSON is the primary data format for mobile app communication with backend services. Mobile environments present unique challenges for JSON handling: limited bandwidth, battery constraints, memory pressure, and offline requirements. This guide covers JSON optimization for mobile, including payload reduction, caching strategies, offline serialization, and platform-specific APIs for iOS (Swift) and Android (Kotlin). Use our JSON Minifier to reduce mobile payload sizes and JSON Compress for maximum compression.
Mobile JSON Challenges
| Challenge | Impact | Solution |
|---|---|---|
| Network latency (3G/4G) | 300-1000ms per request | Minify JSON, use Gzip, batch requests |
| Data plan costs | User pays per MB | Reduce payload size 70-90% with compression |
| Battery consumption | JSON parsing uses CPU | Use native parsers, cache parsed results |
| Memory constraints | Mobile devices have 1-4GB RAM | Stream large JSON, paginate API responses |
| Offline operation | No network connectivity | Cache JSON locally (Room, CoreData, MMKV) |
iOS: JSON with Swift (Codable)
import Foundation
// Define model with Codable
struct User: Codable {
let id: Int
let name: String
let email: String
let metadata: [String: String]?
}
// Decode JSON
let jsonString = """
{"id": 1, "name": "Alice", "email": "alice@example.com"}
"""
let jsonData = jsonString.data(using: .utf8)!
let decoder = JSONDecoder()
let user = try decoder.decode(User.self, from: jsonData)
// Encode to JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let encodedData = try encoder.encode(user)
let jsonOutput = String(data: encodedData, encoding: .utf8)!
// Custom key mapping
struct APIPost: Codable {
let id: Int
let title: String
let createdAt: Date
enum CodingKeys: String, CodingKey {
case id
case title
case createdAt = "created_at" // snake_case to camelCase
}
}
Android: JSON with Kotlin (Moshi/Kotlinx Serialization)
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
// Define data class
data class User(
val id: Int,
val name: String,
val email: String,
val metadata: Map<String, String>? = null
)
// Parse JSON with Moshi
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
val adapter = moshi.adapter(User::class.java)
val jsonString = """{"id": 1, "name": "Alice", "email": "alice@example.com"}"""
val user = adapter.fromJson(jsonString)
// Serialize
val jsonOutput = adapter.toJson(user)
// Kotlinx Serialization
// @Serializable
// data class User(@SerialName("id") val id: Int, ...)
Payload Reduction for Mobile
// Full response (2.4 KB)
{
"users": [
{
"id": 1,
"name": "Alice",
"email": "alice@example.com",
"avatar": "https://cdn.example.com/avatars/alice.jpg",
"lastLogin": "2025-01-15T10:30:00Z",
"preferences": {
"theme": "dark",
"notifications": true
},
"address": { ... },
"phone": "+1-555-0100",
"status": "active"
}
// ... more users
]
}
// Mobile-optimized response (0.8 KB, 67% reduction)
// - Shorter keys
// - Omit null fields
// - Remove rarely-used fields
// - Use relative timestamps
{
"u": [
{
"i": 1,
"n": "Alice",
"e": "alice@example.com",
"a": "https://cdn.example.com/avatars/alice.jpg",
"ll": 1736932200 // Unix timestamp (no ISO string)
}
]
}
Caching JSON on Mobile
// iOS: Cache JSON to disk
let cache = URLCache(
memoryCapacity: 10 * 1024 * 1024, // 10 MB
diskCapacity: 50 * 1024 * 1024, // 50 MB
diskPath: "json_cache"
)
// Android: Room database for JSON caching
@Entity(tableName = "api_cache")
data class CacheEntry(
@PrimaryKey val endpoint: String,
val json: String,
val timestamp: Long,
val ttl: Long
)
// SQLite/FMDB on iOS
// Use MMKV for key-value JSON cache
// MMKV is 10-50x faster than NSUserDefaults for JSON storage
Mobile JSON Parsing Performance
| Parser | Platform | Time (100KB) | Memory (100KB) |
|---|---|---|---|
| JSONDecoder (Foundation) | iOS | 8ms | 2.1 MB |
| Moshi | Android | 12ms | 2.8 MB |
| Kotlinx Serialization | Android | 10ms | 2.5 MB |
| Gson | Android | 18ms | 3.2 MB |
| simdjson (C wrapper) | Both | 3ms | 1.5 MB |
Offline-First JSON Strategies
- Cache JSON responses on device using local databases or MMKV
- Implement stale-while-revalidate: show cached JSON first, update in background
- Use JSON Patch (RFC 6902) for incremental updates: only send changes
- Queue JSON writes when offline and sync when connectivity returns
- Validate cached JSON with JSON Validator during development
- Use JSON Minifier to reduce storage footprint of cached JSON
Next Steps
Optimize mobile JSON payloads with JSON Minifier. Test compression with JSON Compress. Validate JSON structures with JSON Validator.