Created
January 24, 2018 16:34
-
-
Save vincentdaniel/cb630b03c39084f9ac7a367f922cf342 to your computer and use it in GitHub Desktop.
Revisions
-
Vincent Daniel created this gist
Jan 24, 2018 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,80 @@ 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() }