Configure JSON Naming Strategy in Kotlin Serialization
Learn how to handle snake_case, camelCase, and kebab-case JSON keys with Kotlin's naming strategy options. Covers global strategies and per-field @SerialName overrides.
Detailed Explanation
JSON Naming Strategies in Kotlin
JSON APIs commonly use snake_case while Kotlin uses camelCase. Instead of adding @SerialName to every property, you can configure a global naming strategy.
kotlinx.serialization Naming Strategy (1.6.0+)
val json = Json {
namingStrategy = JsonNamingStrategy.SnakeCase
}
@Serializable
data class UserProfile(
val userId: Int, // maps to "user_id"
val firstName: String, // maps to "first_name"
val lastName: String, // maps to "last_name"
val isActive: Boolean, // maps to "is_active"
val createdAt: String // maps to "created_at"
)
How Snake Case Conversion Works
The strategy splits on camelCase boundaries and joins with underscores:
| Kotlin property | JSON key |
|---|---|
userId |
user_id |
firstName |
first_name |
isActive |
is_active |
apiURL |
api_u_r_l (careful!) |
Overriding Individual Fields
Even with a global strategy, @SerialName takes precedence for specific fields:
val json = Json {
namingStrategy = JsonNamingStrategy.SnakeCase
}
@Serializable
data class Config(
val apiVersion: String, // "api_version" (auto)
@SerialName("APIKey") val apiKey: String // "APIKey" (override)
)
Gson Naming Policy
val gson = GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
Moshi with KotlinJsonAdapterFactory
Moshi does not have a built-in naming strategy. Use @Json(name = "...") per field:
data class User(
@Json(name = "user_id") val userId: Int,
@Json(name = "first_name") val firstName: String
)
Which Approach to Choose?
| Scenario | Recommendation |
|---|---|
| All fields follow snake_case | Global SnakeCase strategy |
| Mixed naming conventions | Per-field @SerialName |
| Legacy API with inconsistencies | Per-field annotations |
| Multi-platform project | kotlinx.serialization global strategy |
Common Pitfall: Acronyms
Consecutive uppercase letters can produce unexpected snake_case results. For properties like apiURL or htmlParser, test the output or use explicit @SerialName to avoid surprises.
Use Case
When migrating from a Python or Ruby backend to a Kotlin-based service, the JSON contracts use snake_case. A global naming strategy avoids hundreds of @SerialName annotations and keeps the Kotlin code idiomatic with camelCase properties.
Try It — JSON to Kotlin
Related Topics
Kotlin Serialization Annotations for JSON Mapping
Serialization
Convert Simple JSON to a Kotlin Data Class
Basic Data Classes
Map JSON String Values to Kotlin Enum Classes
Advanced Patterns
Use Default Values in Kotlin Data Classes for Missing JSON Fields
Serialization
Convert Dynamic JSON Keys to Kotlin Map Types
Collections