Last active
June 22, 2017 01:51
-
-
Save kilink/e882edb1dc52035ef6000075ce774b93 to your computer and use it in GitHub Desktop.
merge data class with ObjectNode
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
fun main(args: Array<String>) { | |
val mapper = ObjectMapper().registerKotlinModule() | |
val obj = Foo("foo", "bar", 3) | |
val obj2 = merge<Foo>(obj, mapper.readValue<ObjectNode>("""{"x": "baz", "z": 5}""")) | |
println("obj=${obj} obj2=${obj2}, obj === obj2 is ${obj === obj2}") | |
} | |
fun <T> merge(obj: Any, json: ObjectNode): T { | |
require(obj::class.isData) { "Object is not an instance of a data class: $obj" } | |
val mapper = ObjectMapper().registerKotlinModule() | |
val copyMethod = obj::class.memberFunctions.find { method -> method.name == "copy" } ?: | |
throw RuntimeException("Couldn't find copy method on instance: $obj") | |
val args = mutableMapOf<KParameter, Any?>() | |
for (param in copyMethod.parameters) { | |
if (param.name == null) { | |
args[param] = obj | |
continue | |
} | |
if (!json.has(param.name)) { | |
if (param.isOptional) { | |
continue | |
} | |
throw RuntimeException("Missing required field: ${param.name}") | |
} | |
val node = json.get(param.name) | |
if (node.isNull && !param.type.isMarkedNullable) { | |
throw RuntimeException("Got null value for non-nullable field: ${param.name}") | |
} | |
val javaType = mapper.constructType(param.type.javaType) | |
args[param] = mapper.readerFor(javaType).readValue(node) | |
} | |
return copyMethod.callBy(args) as T | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment