Created
January 24, 2018 16:34
-
-
Save vincentdaniel/cb630b03c39084f9ac7a367f922cf342 to your computer and use it in GitHub Desktop.
From a file with multiple json messages to one data class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.fasterxml.jackson.core.type.TypeReference | |
import com.fasterxml.jackson.databind.ObjectMapper | |
import java.io.File | |
object Main { | |
/** | |
* - Reads a file that contains multiple json messages: | |
* ``` | |
* {"id":12345,"some_key1":"value1"} | |
* {"id":12346,"some_key1":"value2","some_optional_key2":"value3"} | |
* ... | |
* ``` | |
* - Generates the corresponding data class: | |
* ``` | |
* data class MyClass( | |
* val id: Int? = null, | |
* val someKey1: String? = null, | |
* val someOptionalKey2: String? = null | |
* ) | |
* ``` | |
*/ | |
@JvmStatic | |
fun main(args: Array<String>) { | |
val jsonLines = readFile("sample-data.log") | |
println(jsonLines.toDataClass("MyClass")) | |
} | |
private fun readFile(file: String): List<String> { | |
val inputStream = File(file).inputStream() | |
val lineList = mutableListOf<String>() | |
inputStream.bufferedReader().useLines { lines -> lines.forEach { lineList.add(it)} } | |
return lineList | |
} | |
private fun List<String>.toDataClass(name: String): String = this.extractSchema().toDataClass(name) | |
private fun List<String>.extractSchema(): Map<String, String> { | |
val objectMapper = ObjectMapper() | |
val schema = mutableMapOf<String, String>() | |
this.forEach { schema.updateWith(it.parseSchema(objectMapper)) } | |
return schema | |
} | |
private fun MutableMap<String, String>.updateWith(other: Map<String, String>) { | |
other.forEach { key, value -> | |
this.compute(key, { _, oldValue -> | |
when (oldValue) { | |
null -> value | |
"null" -> value | |
else -> oldValue | |
} | |
}) | |
} | |
} | |
private fun Map<String, String>.toDataClass(name: String): String { | |
val lineSeparator = System.getProperty("line.separator") ?: "\n" | |
val types = this.map { (key, javaType) -> | |
val kotlinType = when (javaType) { | |
"class java.lang.Integer" -> "Int" | |
"class java.lang.Boolean" -> "Boolean" | |
else -> "String" | |
} | |
"val $key: $kotlinType? = null" | |
}.joinToString(",$lineSeparator") | |
return "data class $name($types)" | |
} | |
private fun String.parseSchema(objectMapper: ObjectMapper): Map<String, String> { | |
val jsonMap: Map<String, Any?> = objectMapper.readValue(this, object : TypeReference<Map<String, Any?>>() {}) | |
return jsonMap.map { (key, value) -> | |
Pair(key.toCamelCase(), value?.javaClass.toString()) | |
}.toMap().toSortedMap() | |
} | |
private fun String.toCamelCase(): String = this.split('_').joinToString("") { it.capitalize() }.decapitalize() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment