Kotlin Data Class vs Regular Class for JSON Models
Understand when to use data class vs regular class for JSON models in Kotlin. Covers generated methods, equality semantics, inheritance limitations, and mutable vs immutable patterns.
Detailed Explanation
Data Class vs Regular Class for JSON
The converter generates data class by default, but sometimes a regular class is more appropriate. Understanding the differences helps you make the right choice.
What Data Class Gives You
data class User(val id: Int, val name: String, val email: String)
// Auto-generated:
// - equals() / hashCode() based on all properties
// - toString() -> "User(id=1, name=Alice, email=alice@example.com)"
// - copy() -> user.copy(name = "Bob")
// - componentN() -> val (id, name, email) = user
When Data Class Is Better
- Immutable value objects -- most JSON models are read-only after deserialization
- Comparison by value -- two users with the same fields are equal
- Debugging -- meaningful
toString()output - Pattern matching -- destructuring in
whenexpressions andletblocks
When Regular Class Is Better
Inheritance required:
// Data classes cannot be abstract or open
open class BaseModel(
open val id: Int,
open val createdAt: String
)
class User(
override val id: Int,
override val createdAt: String,
val name: String
) : BaseModel(id, createdAt)
Mutable state:
class MutableUser(
var id: Int,
var name: String,
var email: String
) {
fun updateFrom(json: JsonObject) {
json["name"]?.jsonPrimitive?.content?.let { name = it }
}
}
Custom equality:
class Entity(val id: Int, val name: String, val version: Int) {
// Equality based only on id, not all fields
override fun equals(other: Any?) =
other is Entity && id == other.id
override fun hashCode() = id.hashCode()
}
Comparison Table
| Feature | data class | class |
|---|---|---|
| Auto equals/hashCode | Yes (all props) | No (identity) |
| Auto toString | Yes | No |
| copy() | Yes | No |
| Destructuring | Yes | No |
| Inheritance | Limited | Full |
| Mutable properties | Possible but discouraged | Natural |
Best Practice for JSON Models
- Start with data class -- it is correct for 90% of JSON models
- Switch to class when you need inheritance hierarchies or identity-based equality
- Use sealed classes for polymorphic JSON (not regular inheritance)
- Keep data classes immutable -- use
valnotvar, usecopy()for modifications
Value Class for Single-Field Wrappers
@JvmInline
value class UserId(val value: Int)
data class User(
val id: UserId,
val name: String
)
Value classes add type safety without runtime overhead, useful for wrapping primitive ID fields to prevent mixing up user IDs and order IDs.
Use Case
When designing the model layer for an Android MVVM architecture or a Kotlin backend service, choosing between data class and regular class affects testability, debugging, and maintenance. Data classes are the correct default for JSON DTOs, with regular classes reserved for stateful entities.
Try It — JSON to Kotlin
Related Topics
Convert Simple JSON to a Kotlin Data Class
Basic Data Classes
Model Polymorphic JSON with Kotlin Sealed Classes
Advanced Patterns
Add Companion Object Factory Methods to Kotlin Data Classes
Advanced Patterns
Use Kotlin Generics for Reusable JSON Response Wrappers
Advanced Patterns
Map JSON String Values to Kotlin Enum Classes
Advanced Patterns