Try it yourself with our free Json To Csv tool — runs entirely in your browser, no signup needed.

How to Convert JSON to CSV in Kotlin

How to Convert JSON to CSV in Kotlin

Converting JSON data to CSV is a common requirement in many applications, especially when working with data exchange or reporting. In this article, we will explore how to achieve this in Kotlin, a modern and concise programming language. We will provide a step-by-step guide, covering the most common use case, edge cases, and performance tips.

Quick Example

Here is a minimal example that converts a JSON string to a CSV string:

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

fun jsonToCsv(jsonString: String): String {
    val gson = Gson()
    val listType = object : TypeToken<List<Map<String, String>>>() {}.type
    val dataList = gson.fromJson(jsonString, listType)
    return dataList.joinToString("\n") { row ->
        row.values.joinToString(",")
    }
}

You can use this function like this:

val jsonString = "[{\"name\":\"John\",\"age\":\"25\"},{\"name\":\"Alice\",\"age\":\"30\"}]"
val csvString = jsonToCsv(jsonString)
println(csvString) // Output: John,25\nAlice,30

Step-by-Step Breakdown

Let's break down the code:

  1. We import the necessary libraries: com.google.gson.Gson for JSON parsing and com.google.gson.reflect.TypeToken for type safety.
  2. We define a function jsonToCsv that takes a JSON string as input and returns a CSV string.
  3. We create a Gson instance to parse the JSON string.
  4. We define a TypeToken to specify the type of data we expect: a list of maps with string keys and values.
  5. We use Gson to parse the JSON string into a list of maps.
  6. We use the joinToString function to concatenate the values of each map into a CSV string.

Handling Edge Cases

Empty/Null Input

If the input JSON string is empty or null, we should return an empty CSV string:

fun jsonToCsv(jsonString: String?): String {
    if (jsonString.isNullOrEmpty()) return ""
    // ...
}

Invalid Input

If the input JSON string is invalid, Gson will throw a JsonSyntaxException. We can catch this exception and return an error message:

fun jsonToCsv(jsonString: String): String {
    try {
        // ...
    } catch (e: JsonSyntaxException) {
        return "Invalid JSON input"
    }
}

Large Input

If the input JSON string is very large, we may need to process it in chunks to avoid memory issues. We can use a JsonReader to read the JSON string chunk by chunk:

fun jsonToCsv(jsonString: String): String {
    val jsonReader = JsonReader(StringReader(jsonString))
    val csvBuilder = StringBuilder()
    jsonReader.beginArray()
    while (jsonReader.hasNext()) {
        jsonReader.beginObject()
        while (jsonReader.hasNext()) {
            csvBuilder.append(jsonReader.nextName()).append(",")
            csvBuilder.append(jsonReader.nextString()).append("\n")
        }
        jsonReader.endObject()
    }
    jsonReader.endArray()
    return csvBuilder.toString()
}

Unicode/Special Characters

If the input JSON string contains Unicode or special characters, we need to ensure that they are properly encoded in the CSV output. We can use the StringEscapeUtils class from the Apache Commons Lang library to escape special characters:

import org.apache.commons.lang3.StringEscapeUtils

fun jsonToCsv(jsonString: String): String {
    // ...
    val csvString = dataList.joinToString("\n") { row ->
        row.values.joinToString(",") { value ->
            StringEscapeUtils.escapeCsv(value)
        }
    }
    return csvString
}

Common Mistakes

Wrong TypeToken

Using a wrong TypeToken can lead to incorrect parsing of the JSON string:

// Wrong
val listType = object : TypeToken<List<String>>() {}.type
// Correct
val listType = object : TypeToken<List<Map<String, String>>>() {}.type

Missing Error Handling

Not handling errors can lead to unexpected behavior:

// Wrong
fun jsonToCsv(jsonString: String): String {
    val gson = Gson()
    val dataList = gson.fromJson(jsonString, listType)
    return dataList.joinToString("\n") { row ->
        row.values.joinToString(",")
    }
}
// Correct
fun jsonToCsv(jsonString: String): String {
    try {
        // ...
    } catch (e: JsonSyntaxException) {
        return "Invalid JSON input"
    }
}

Inefficient CSV Generation

Using the joinToString function can be inefficient for large datasets. Using a StringBuilder can be more efficient:

// Wrong
return dataList.joinToString("\n") { row ->
    row.values.joinToString(",")
}
// Correct
val csvBuilder = StringBuilder()
dataList.forEach { row ->
    csvBuilder.append(row.values.joinToString(",")).append("\n")
}
return csvBuilder.toString()

Performance Tips

  1. Use a JsonReader to read the JSON string chunk by chunk for large inputs.
  2. Use a StringBuilder to generate the CSV string instead of using the joinToString function.
  3. Use the StringEscapeUtils class to escape special characters in the CSV output.

FAQ

Q: What is the best way to handle invalid JSON input?

A: You can catch the JsonSyntaxException thrown by Gson and return an error message.

Q: How can I handle large JSON inputs?

A: You can use a JsonReader to read the JSON string chunk by chunk.

Q: How can I escape special characters in the CSV output?

A: You can use the StringEscapeUtils class from the Apache Commons Lang library.

Q: What is the most efficient way to generate the CSV string?

A: You can use a StringBuilder instead of the joinToString function.

Q: Can I use this code for other data formats?

A: No, this code is specifically designed for JSON to CSV conversion. You may need to modify it for other data formats.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp